system configuration seed added
This commit is contained in:
parent
31354f2825
commit
53bc624094
124
CONSOLE_LOGS_CLEANED.md
Normal file
124
CONSOLE_LOGS_CLEANED.md
Normal file
@ -0,0 +1,124 @@
|
||||
# Console Logs Cleanup Summary
|
||||
|
||||
## Changes Applied
|
||||
|
||||
All verbose, redundant, and confusing console logs have been removed or simplified to keep only essential one-line messages helpful for bug tracking.
|
||||
|
||||
## What Was Kept ✅
|
||||
|
||||
**Server Startup:**
|
||||
- `🚀 Server running on port ${PORT} | ${environment}` - Single line server status
|
||||
|
||||
**Critical Errors:**
|
||||
- `❌ Database connection failed`
|
||||
- `❌ Unable to start server`
|
||||
- `❌ SSO Callback failed`
|
||||
- `❌ Get Users failed`
|
||||
- `❌ Authorization check failed`
|
||||
- `❌ Admin authorization failed`
|
||||
- `❌ Migration failed`
|
||||
- `❌ Configuration seeding error`
|
||||
- `❌ TAT Error loading working hours/holidays`
|
||||
|
||||
**Migration Status:**
|
||||
- `✅ Migrations up-to-date`
|
||||
- `🔄 Running ${count} migration(s)...`
|
||||
- `✅ ${migration-name}` - Per migration success
|
||||
- `✅ Applied ${count} migration(s)` - Final summary
|
||||
|
||||
**Graceful Shutdown:**
|
||||
- `🛑 SIGTERM signal received: closing HTTP server`
|
||||
- `🛑 SIGINT signal received: closing HTTP server`
|
||||
|
||||
## What Was Removed ❌
|
||||
|
||||
### Multi-line Configuration Dumps
|
||||
- ~~TAT Configuration details (working hours, thresholds, test mode)~~
|
||||
- ~~System Configuration details (environment, version, features)~~
|
||||
- ~~Working hours cache loaded messages~~
|
||||
|
||||
### Verbose Development Logs
|
||||
- ~~Database connection established~~
|
||||
- ~~Database models synchronized~~
|
||||
- ~~Socket.IO server initialized~~
|
||||
- ~~Socket.IO client connected with socket.id~~
|
||||
- ~~Auth routes loaded~~
|
||||
- ~~Holiday calendar loaded~~
|
||||
|
||||
### Migration Details
|
||||
- ~~Individual table created messages~~
|
||||
- ~~Individual column added messages~~
|
||||
- ~~Index created messages~~
|
||||
- ~~Conversion progress messages~~
|
||||
|
||||
### Database Query Logging
|
||||
- **Disabled SQL query logging** in `database.ts` - previously showed ALL database queries in development mode
|
||||
|
||||
## File Changes
|
||||
|
||||
### Core Files
|
||||
1. **src/server.ts** - Simplified to single line startup message
|
||||
2. **src/app.ts** - Removed database connection messages, kept only errors
|
||||
3. **src/config/tat.config.ts** - Disabled multi-line TAT config logging
|
||||
4. **src/config/system.config.ts** - Disabled multi-line system config logging
|
||||
5. **src/config/database.ts** - **Disabled SQL query logging** (was showing every SELECT/INSERT/UPDATE)
|
||||
6. **src/realtime/socket.ts** - Removed Socket.IO initialization and connection logs
|
||||
7. **src/utils/tatTimeUtils.ts** - Removed verbose cache loading messages, kept errors
|
||||
8. **src/routes/auth.routes.ts** - Removed route loading message
|
||||
9. **src/middlewares/authorization.middleware.ts** - Improved error messages
|
||||
|
||||
### Migration Files (All)
|
||||
- **2025103000-create-users.ts**
|
||||
- **2025110501-alter-tat-days-to-generated.ts**
|
||||
- **20251105-add-skip-fields-to-approval-levels.ts**
|
||||
- **20251104-create-admin-config.ts**
|
||||
- **20251104-create-holidays.ts**
|
||||
- **20251104-create-kpi-views.ts**
|
||||
|
||||
All replaced verbose console logs with inline comments.
|
||||
|
||||
### Scripts
|
||||
- **src/scripts/migrate.ts** - Streamlined migration output
|
||||
- **src/scripts/seed-admin-config.ts** - Simplified seed messages
|
||||
|
||||
## New Clean Console Output
|
||||
|
||||
### Development Server Start
|
||||
```
|
||||
🚀 Server running on port 5000 | development
|
||||
```
|
||||
|
||||
### Running Migrations
|
||||
```
|
||||
🔄 Running 2 migration(s)...
|
||||
✅ 2025103000-create-users
|
||||
✅ 2025110501-alter-tat-days-to-generated
|
||||
✅ Applied 2 migration(s)
|
||||
```
|
||||
|
||||
### No More Clutter
|
||||
- ❌ No SQL query logs
|
||||
- ❌ No multi-line config dumps
|
||||
- ❌ No verbose socket connection messages
|
||||
- ❌ No redundant "table created" messages
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Cleaner Logs** - Easy to scan for errors and important events
|
||||
2. **Better Performance** - No overhead from logging every SQL query
|
||||
3. **Easier Debugging** - Critical errors stand out with ❌ emoji
|
||||
4. **Production Ready** - Minimal logging suitable for production environments
|
||||
|
||||
## To Enable Debug Logging (If Needed)
|
||||
|
||||
To temporarily enable SQL query logging for debugging:
|
||||
|
||||
```typescript
|
||||
// In Re_Backend/src/config/database.ts
|
||||
logging: console.log // Change from false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Summary:** Reduced ~100+ console log statements to ~20 essential one-liners for bug tracking.
|
||||
|
||||
@ -21,7 +21,8 @@
|
||||
"db:migrate:undo": "sequelize-cli db:migrate:undo",
|
||||
"db:seed": "sequelize-cli db:seed:all",
|
||||
"clean": "rm -rf dist",
|
||||
"migrate": "ts-node src/scripts/migrate.ts"
|
||||
"migrate": "ts-node -r tsconfig-paths/register src/scripts/migrate.ts",
|
||||
"seed:config": "ts-node -r tsconfig-paths/register src/scripts/seed-admin-config.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google-cloud/storage": "^7.14.0",
|
||||
|
||||
@ -21,11 +21,6 @@ const userService = new UserService();
|
||||
const initializeDatabase = async () => {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log('✅ Database connection established successfully');
|
||||
|
||||
// Sync models (create tables if they don't exist)
|
||||
// await sequelize.sync({ force: false });
|
||||
console.log('✅ Database models synchronized (sync disabled)');
|
||||
} catch (error) {
|
||||
console.error('❌ Database connection failed:', error);
|
||||
}
|
||||
@ -130,7 +125,7 @@ app.post('/api/v1/auth/sso-callback', async (req: express.Request, res: express.
|
||||
timestamp: new Date()
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('SSO Callback Error:', error);
|
||||
console.error('❌ SSO Callback failed:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Internal server error',
|
||||
@ -169,7 +164,7 @@ app.get('/api/v1/users', async (_req: express.Request, res: express.Response): P
|
||||
timestamp: new Date()
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Get Users Error:', error);
|
||||
console.error('❌ Get Users failed:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Internal server error',
|
||||
|
||||
@ -10,7 +10,7 @@ const sequelize = new Sequelize({
|
||||
username: process.env.DB_USER || 'postgres',
|
||||
password: process.env.DB_PASSWORD || 'postgres',
|
||||
dialect: 'postgres',
|
||||
logging: process.env.NODE_ENV === 'development' ? console.log : false,
|
||||
logging: false, // Disable SQL query logging for cleaner console output
|
||||
pool: {
|
||||
min: parseInt(process.env.DB_POOL_MIN || '2', 10),
|
||||
max: parseInt(process.env.DB_POOL_MAX || '10', 10),
|
||||
|
||||
@ -149,14 +149,7 @@ export function getPublicConfig() {
|
||||
* Log system configuration on startup
|
||||
*/
|
||||
export function logSystemConfig(): void {
|
||||
console.log('⚙️ System Configuration:');
|
||||
console.log(` - Environment: ${SYSTEM_CONFIG.APP_ENV}`);
|
||||
console.log(` - Version: ${SYSTEM_CONFIG.APP_VERSION}`);
|
||||
console.log(` - Working Hours: ${SYSTEM_CONFIG.WORKING_HOURS.START_HOUR}:00 - ${SYSTEM_CONFIG.WORKING_HOURS.END_HOUR}:00`);
|
||||
console.log(` - Max File Size: ${SYSTEM_CONFIG.UPLOAD.MAX_FILE_SIZE_MB} MB`);
|
||||
console.log(` - Max Approval Levels: ${SYSTEM_CONFIG.WORKFLOW.MAX_APPROVAL_LEVELS}`);
|
||||
console.log(` - AI Conclusion: ${SYSTEM_CONFIG.FEATURES.ENABLE_AI_CONCLUSION ? 'Enabled' : 'Disabled'}`);
|
||||
console.log(` - TAT Test Mode: ${SYSTEM_CONFIG.TAT.TEST_MODE ? 'ENABLED (1h = 1min)' : 'DISABLED'}`);
|
||||
// System config logging disabled - use environment variables to verify settings
|
||||
}
|
||||
|
||||
export default SYSTEM_CONFIG;
|
||||
|
||||
@ -65,12 +65,7 @@ export function isTestMode(): boolean {
|
||||
* Log TAT configuration on startup
|
||||
*/
|
||||
export function logTatConfig(): void {
|
||||
console.log('⏰ TAT Configuration:');
|
||||
console.log(` - Test Mode: ${TAT_CONFIG.TEST_MODE ? 'ENABLED (1 hour = 1 minute)' : 'DISABLED'}`);
|
||||
console.log(` - Working Hours: ${TAT_CONFIG.WORK_START_HOUR}:00 - ${TAT_CONFIG.WORK_END_HOUR}:00`);
|
||||
console.log(` - Working Days: Monday - Friday`);
|
||||
console.log(` - Redis: ${TAT_CONFIG.REDIS_URL}`);
|
||||
console.log(` - Thresholds: ${TAT_CONFIG.THRESHOLD_50_PERCENT}%, ${TAT_CONFIG.THRESHOLD_75_PERCENT}%, ${TAT_CONFIG.THRESHOLD_100_PERCENT}%`);
|
||||
// TAT config logging disabled - use environment variables to verify settings
|
||||
}
|
||||
|
||||
export default TAT_CONFIG;
|
||||
|
||||
@ -91,7 +91,7 @@ export function requireParticipantTypes(allowed: AllowedType[]) {
|
||||
|
||||
return res.status(403).json({ success: false, error: 'Insufficient permissions' });
|
||||
} catch (err) {
|
||||
console.error('Authorization check error:', err);
|
||||
console.error('❌ Authorization check failed:', err);
|
||||
return res.status(500).json({ success: false, error: 'Authorization check failed' });
|
||||
}
|
||||
};
|
||||
@ -114,7 +114,7 @@ export function requireAdmin(req: Request, res: Response, next: NextFunction): v
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error('Admin authorization check error:', error);
|
||||
console.error('❌ Admin authorization failed:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Authorization check failed'
|
||||
|
||||
@ -105,11 +105,11 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
name: 'users_employee_id_idx'
|
||||
});
|
||||
|
||||
console.log('✅ Created users table with indexes');
|
||||
// Users table created
|
||||
}
|
||||
|
||||
export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
await queryInterface.dropTable('users');
|
||||
console.log('✅ Dropped users table');
|
||||
// Users table dropped
|
||||
}
|
||||
|
||||
|
||||
@ -122,15 +122,13 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
await queryInterface.sequelize.query('CREATE INDEX IF NOT EXISTS "admin_configurations_is_editable" ON "admin_configurations" ("is_editable");');
|
||||
await queryInterface.sequelize.query('CREATE INDEX IF NOT EXISTS "admin_configurations_sort_order" ON "admin_configurations" ("sort_order");');
|
||||
|
||||
console.log('✅ Admin configurations table created successfully');
|
||||
console.log('Note: Default configurations will be seeded on first server start');
|
||||
// Admin config table created
|
||||
}
|
||||
|
||||
export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
await queryInterface.dropTable('admin_configurations');
|
||||
await queryInterface.sequelize.query('DROP TYPE IF EXISTS "enum_admin_configurations_config_category";');
|
||||
await queryInterface.sequelize.query('DROP TYPE IF EXISTS "enum_admin_configurations_value_type";');
|
||||
|
||||
console.log('✅ Admin configurations table dropped');
|
||||
// Admin config table dropped
|
||||
}
|
||||
|
||||
|
||||
@ -95,13 +95,12 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
await queryInterface.sequelize.query('CREATE INDEX IF NOT EXISTS "holidays_holiday_type" ON "holidays" ("holiday_type");');
|
||||
await queryInterface.sequelize.query('CREATE INDEX IF NOT EXISTS "holidays_created_by" ON "holidays" ("created_by");');
|
||||
|
||||
console.log('✅ Holidays table created successfully');
|
||||
// Holidays table created
|
||||
}
|
||||
|
||||
export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
await queryInterface.dropTable('holidays');
|
||||
await queryInterface.sequelize.query('DROP TYPE IF EXISTS "enum_holidays_holiday_type";');
|
||||
|
||||
console.log('✅ Holidays table dropped successfully');
|
||||
// Holidays table dropped
|
||||
}
|
||||
|
||||
|
||||
@ -249,7 +249,7 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
GROUP BY w.request_id, w.request_number, w.title, w.status;
|
||||
`);
|
||||
|
||||
console.log('✅ KPI views created successfully');
|
||||
// KPI views created
|
||||
}
|
||||
|
||||
export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
@ -261,7 +261,6 @@ export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
await queryInterface.sequelize.query('DROP VIEW IF EXISTS vw_approver_performance;');
|
||||
await queryInterface.sequelize.query('DROP VIEW IF EXISTS vw_tat_compliance;');
|
||||
await queryInterface.sequelize.query('DROP VIEW IF EXISTS vw_request_volume_summary;');
|
||||
|
||||
console.log('✅ KPI views dropped successfully');
|
||||
// KPI views dropped
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
// Check if table exists first
|
||||
const tables = await queryInterface.showAllTables();
|
||||
if (!tables.includes('approval_levels')) {
|
||||
console.log('⚠️ approval_levels table does not exist yet, skipping...');
|
||||
// Table doesn't exist yet, skipping
|
||||
return;
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
defaultValue: false,
|
||||
comment: 'Indicates if this approver was skipped by initiator'
|
||||
});
|
||||
console.log(' ✅ Added is_skipped column');
|
||||
// Added is_skipped column
|
||||
}
|
||||
|
||||
if (!tableDescription.skipped_at) {
|
||||
@ -34,7 +34,7 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
allowNull: true,
|
||||
comment: 'Timestamp when approver was skipped'
|
||||
});
|
||||
console.log(' ✅ Added skipped_at column');
|
||||
// Added skipped_at column
|
||||
}
|
||||
|
||||
if (!tableDescription.skipped_by) {
|
||||
@ -49,7 +49,7 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
onDelete: 'SET NULL',
|
||||
comment: 'User ID who skipped this approver'
|
||||
});
|
||||
console.log(' ✅ Added skipped_by column');
|
||||
// Added skipped_by column
|
||||
}
|
||||
|
||||
if (!tableDescription.skip_reason) {
|
||||
@ -58,7 +58,7 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
allowNull: true,
|
||||
comment: 'Reason for skipping this approver'
|
||||
});
|
||||
console.log(' ✅ Added skip_reason column');
|
||||
// Added skip_reason column
|
||||
}
|
||||
|
||||
// Check if index exists before creating
|
||||
@ -73,14 +73,13 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
is_skipped: true
|
||||
}
|
||||
});
|
||||
console.log(' ✅ Added idx_approval_levels_skipped index');
|
||||
// Index added
|
||||
}
|
||||
} catch (error) {
|
||||
// Index might already exist, which is fine
|
||||
console.log(' ℹ️ Index already exists or could not be created');
|
||||
// Index already exists
|
||||
}
|
||||
|
||||
console.log('✅ Skip-related fields migration completed');
|
||||
// Skip fields added
|
||||
}
|
||||
|
||||
export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
@ -93,6 +92,6 @@ export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
await queryInterface.removeColumn('approval_levels', 'skipped_at');
|
||||
await queryInterface.removeColumn('approval_levels', 'is_skipped');
|
||||
|
||||
console.log('✅ Removed skip-related fields from approval_levels table');
|
||||
// Skip fields removed
|
||||
}
|
||||
|
||||
|
||||
@ -22,11 +22,11 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
const column = result[0] as any;
|
||||
|
||||
if (column && column.is_generated === 's') {
|
||||
console.log('✅ tat_days is already a GENERATED STORED column - skipping migration');
|
||||
// Already a GENERATED column, skipping
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📝 Converting tat_days to GENERATED STORED column...');
|
||||
// Converting tat_days to GENERATED column
|
||||
|
||||
// Step 1: Drop the existing regular column
|
||||
await queryInterface.sequelize.query(`
|
||||
@ -41,11 +41,11 @@ export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
GENERATED ALWAYS AS (CAST(CEIL(tat_hours / 24.0) AS INTEGER)) STORED;
|
||||
`);
|
||||
|
||||
console.log('✅ tat_days is now a GENERATED STORED column - will auto-calculate from tat_hours');
|
||||
// tat_days is now auto-calculated
|
||||
}
|
||||
|
||||
export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
console.log('⚠️ Rolling back: Converting tat_days from GENERATED to regular column');
|
||||
// Rolling back to regular column
|
||||
|
||||
// Drop the generated column
|
||||
await queryInterface.sequelize.query(`
|
||||
@ -71,6 +71,6 @@ export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
ALTER COLUMN tat_days SET NOT NULL;
|
||||
`);
|
||||
|
||||
console.log('✅ Rolled back to regular INTEGER column');
|
||||
// Rolled back successfully
|
||||
}
|
||||
|
||||
|
||||
@ -15,8 +15,6 @@ export function initSocket(httpServer: any) {
|
||||
const configured = (process.env.FRONTEND_ORIGIN || '').split(',').map(s => s.trim()).filter(Boolean);
|
||||
const origins = configured.length ? configured : defaultOrigins;
|
||||
|
||||
console.log('🔌 Initializing Socket.IO server with origins:', origins);
|
||||
|
||||
io = new Server(httpServer, {
|
||||
cors: {
|
||||
origin: origins,
|
||||
@ -27,10 +25,7 @@ export function initSocket(httpServer: any) {
|
||||
transports: ['websocket', 'polling']
|
||||
});
|
||||
|
||||
console.log('✅ Socket.IO server initialized');
|
||||
|
||||
io.on('connection', (socket: any) => {
|
||||
console.log('🔗 Client connected:', socket.id);
|
||||
let currentRequestId: string | null = null;
|
||||
let currentUserId: string | null = null;
|
||||
|
||||
|
||||
@ -8,8 +8,6 @@ import { asyncHandler } from '../middlewares/errorHandler.middleware';
|
||||
const router = Router();
|
||||
const authController = new AuthController();
|
||||
|
||||
console.log('✅ Auth routes loaded - token-exchange endpoint registered');
|
||||
|
||||
// Token exchange endpoint (no authentication required) - for localhost development
|
||||
router.post('/token-exchange',
|
||||
validateBody(tokenExchangeSchema),
|
||||
|
||||
@ -63,7 +63,7 @@ async function ensureMigrationsTable(queryInterface: QueryInterface): Promise<vo
|
||||
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
console.log('✅ Created migrations tracking table');
|
||||
// Migrations table created
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error creating migrations table:', error);
|
||||
@ -106,7 +106,6 @@ async function markMigrationExecuted(name: string): Promise<void> {
|
||||
async function run() {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log('📦 Database connected');
|
||||
|
||||
const queryInterface = sequelize.getQueryInterface();
|
||||
|
||||
@ -122,33 +121,29 @@ async function run() {
|
||||
);
|
||||
|
||||
if (pendingMigrations.length === 0) {
|
||||
console.log('✅ All migrations are up-to-date (no new migrations to run)');
|
||||
console.log('✅ Migrations up-to-date');
|
||||
process.exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`🔄 Running ${pendingMigrations.length} pending migration(s)...\n`);
|
||||
console.log(`🔄 Running ${pendingMigrations.length} migration(s)...`);
|
||||
|
||||
// Run each pending migration
|
||||
for (const migration of pendingMigrations) {
|
||||
try {
|
||||
console.log(`⏳ Running: ${migration.name}`);
|
||||
await migration.module.up(queryInterface);
|
||||
await markMigrationExecuted(migration.name);
|
||||
console.log(`✅ Completed: ${migration.name}\n`);
|
||||
console.log(`✅ ${migration.name}`);
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed: ${migration.name}`);
|
||||
console.error('Error:', error.message);
|
||||
console.error(`❌ Migration failed: ${migration.name} - ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n✅ Successfully applied ${pendingMigrations.length} migration(s)`);
|
||||
console.log(`📊 Total migrations: ${executedMigrations.length + pendingMigrations.length}`);
|
||||
console.log(`✅ Applied ${pendingMigrations.length} migration(s)`);
|
||||
process.exit(0);
|
||||
} catch (err: any) {
|
||||
console.error('\n❌ Migration failed:', err.message);
|
||||
console.error('\nStack trace:', err.stack);
|
||||
console.error('❌ Migration failed:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
392
src/scripts/seed-admin-config.ts
Normal file
392
src/scripts/seed-admin-config.ts
Normal file
@ -0,0 +1,392 @@
|
||||
/**
|
||||
* Manual script to seed admin configurations
|
||||
* Run this if configurations are not auto-seeding on server startup
|
||||
*
|
||||
* Usage: npm run seed:config
|
||||
*/
|
||||
|
||||
import { sequelize } from '../config/database';
|
||||
import { QueryTypes } from 'sequelize';
|
||||
|
||||
async function seedAdminConfigurations() {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
|
||||
// Check if configurations already exist
|
||||
const count = await sequelize.query(
|
||||
'SELECT COUNT(*) as count FROM admin_configurations',
|
||||
{ type: QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
const existingCount = (count[0] as any).count;
|
||||
|
||||
if (existingCount > 0) {
|
||||
console.log(`⚠️ Found ${existingCount} existing configurations. Delete them first or skip this script.`);
|
||||
const readline = require('readline').createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
const answer = await new Promise<string>((resolve) => {
|
||||
readline.question('Delete existing and re-seed? (yes/no): ', resolve);
|
||||
});
|
||||
|
||||
readline.close();
|
||||
|
||||
if (answer.toLowerCase() !== 'yes') {
|
||||
console.log('❌ Aborted. No changes made.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
await sequelize.query('DELETE FROM admin_configurations');
|
||||
console.log('✅ Existing configurations deleted');
|
||||
}
|
||||
|
||||
console.log('📝 Seeding admin configurations...');
|
||||
|
||||
// Insert all default configurations
|
||||
await sequelize.query(`
|
||||
INSERT INTO admin_configurations (
|
||||
config_id, config_key, config_category, config_value, value_type,
|
||||
display_name, description, default_value, is_editable, is_sensitive,
|
||||
validation_rules, ui_component, sort_order, requires_restart,
|
||||
created_at, updated_at
|
||||
) VALUES
|
||||
-- TAT Settings
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'DEFAULT_TAT_EXPRESS_HOURS',
|
||||
'TAT_SETTINGS',
|
||||
'24',
|
||||
'NUMBER',
|
||||
'Default TAT for Express Priority',
|
||||
'Default turnaround time in hours for express priority requests (calendar days, 24/7)',
|
||||
'24',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 168}'::jsonb,
|
||||
'number',
|
||||
1,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'DEFAULT_TAT_STANDARD_HOURS',
|
||||
'TAT_SETTINGS',
|
||||
'48',
|
||||
'NUMBER',
|
||||
'Default TAT for Standard Priority',
|
||||
'Default turnaround time in hours for standard priority requests (working hours only)',
|
||||
'48',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 336}'::jsonb,
|
||||
'number',
|
||||
2,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'TAT_THRESHOLD_WARNING',
|
||||
'TAT_SETTINGS',
|
||||
'50',
|
||||
'NUMBER',
|
||||
'TAT Warning Threshold (%)',
|
||||
'Percentage of TAT elapsed when first warning notification is sent',
|
||||
'50',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'number',
|
||||
3,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'TAT_THRESHOLD_CRITICAL',
|
||||
'TAT_SETTINGS',
|
||||
'75',
|
||||
'NUMBER',
|
||||
'TAT Critical Threshold (%)',
|
||||
'Percentage of TAT elapsed when critical notification is sent',
|
||||
'75',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'number',
|
||||
4,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'TAT_TEST_MODE',
|
||||
'TAT_SETTINGS',
|
||||
'false',
|
||||
'BOOLEAN',
|
||||
'TAT Test Mode',
|
||||
'Enable test mode where 1 TAT hour = 1 minute (for development/testing only)',
|
||||
'false',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'switch',
|
||||
5,
|
||||
true,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
|
||||
-- Working Hours Settings
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'WORK_START_HOUR',
|
||||
'WORKING_HOURS',
|
||||
'9',
|
||||
'NUMBER',
|
||||
'Work Day Start Hour',
|
||||
'Hour when work day starts (24-hour format, e.g., 9 for 9:00 AM)',
|
||||
'9',
|
||||
true,
|
||||
false,
|
||||
'{"min": 0, "max": 23}'::jsonb,
|
||||
'number',
|
||||
10,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'WORK_END_HOUR',
|
||||
'WORKING_HOURS',
|
||||
'18',
|
||||
'NUMBER',
|
||||
'Work Day End Hour',
|
||||
'Hour when work day ends (24-hour format, e.g., 18 for 6:00 PM)',
|
||||
'18',
|
||||
true,
|
||||
false,
|
||||
'{"min": 0, "max": 23}'::jsonb,
|
||||
'number',
|
||||
11,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'WORK_START_DAY',
|
||||
'WORKING_HOURS',
|
||||
'1',
|
||||
'NUMBER',
|
||||
'Work Week Start Day',
|
||||
'Day when work week starts (1 = Monday, 7 = Sunday)',
|
||||
'1',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 7}'::jsonb,
|
||||
'number',
|
||||
12,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'WORK_END_DAY',
|
||||
'WORKING_HOURS',
|
||||
'5',
|
||||
'NUMBER',
|
||||
'Work Week End Day',
|
||||
'Day when work week ends (1 = Monday, 7 = Sunday)',
|
||||
'5',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 7}'::jsonb,
|
||||
'number',
|
||||
13,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'TIMEZONE',
|
||||
'WORKING_HOURS',
|
||||
'Asia/Kolkata',
|
||||
'STRING',
|
||||
'System Timezone',
|
||||
'Timezone for all TAT calculations and scheduling',
|
||||
'Asia/Kolkata',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'select',
|
||||
14,
|
||||
true,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
|
||||
-- Workflow Settings
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'MAX_APPROVAL_LEVELS',
|
||||
'WORKFLOW',
|
||||
'10',
|
||||
'NUMBER',
|
||||
'Maximum Approval Levels',
|
||||
'Maximum number of approval levels allowed per workflow',
|
||||
'10',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 20}'::jsonb,
|
||||
'number',
|
||||
20,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'MAX_PARTICIPANTS',
|
||||
'WORKFLOW',
|
||||
'50',
|
||||
'NUMBER',
|
||||
'Maximum Participants',
|
||||
'Maximum number of participants (spectators + approvers) per request',
|
||||
'50',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'number',
|
||||
21,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
|
||||
-- File Upload Settings
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'MAX_FILE_SIZE_MB',
|
||||
'FILE_UPLOAD',
|
||||
'10',
|
||||
'NUMBER',
|
||||
'Maximum File Size (MB)',
|
||||
'Maximum size for uploaded files in megabytes',
|
||||
'10',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'number',
|
||||
30,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'ALLOWED_FILE_TYPES',
|
||||
'FILE_UPLOAD',
|
||||
'pdf,doc,docx,xls,xlsx,ppt,pptx,jpg,jpeg,png,gif,txt',
|
||||
'STRING',
|
||||
'Allowed File Types',
|
||||
'Comma-separated list of allowed file extensions',
|
||||
'pdf,doc,docx,xls,xlsx,ppt,pptx,jpg,jpeg,png,gif,txt',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'text',
|
||||
31,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
|
||||
-- Feature Toggles
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'ENABLE_AI_CONCLUSION',
|
||||
'FEATURES',
|
||||
'true',
|
||||
'BOOLEAN',
|
||||
'Enable AI-Generated Conclusions',
|
||||
'Allow AI to generate automatic conclusion remarks for approved/rejected requests',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'switch',
|
||||
40,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'ENABLE_PUSH_NOTIFICATIONS',
|
||||
'FEATURES',
|
||||
'true',
|
||||
'BOOLEAN',
|
||||
'Enable Push Notifications',
|
||||
'Send browser push notifications for real-time events',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'switch',
|
||||
41,
|
||||
false,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'ENABLE_EMAIL_NOTIFICATIONS',
|
||||
'FEATURES',
|
||||
'true',
|
||||
'BOOLEAN',
|
||||
'Enable Email Notifications',
|
||||
'Send email notifications for workflow events',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'switch',
|
||||
42,
|
||||
true,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
const finalCount = await sequelize.query(
|
||||
'SELECT COUNT(*) as count FROM admin_configurations',
|
||||
{ type: QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
console.log(`✅ Seeded ${(finalCount[0] as any).count} admin configurations`);
|
||||
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('❌ Error seeding admin configurations:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
if (require.main === module) {
|
||||
seedAdminConfigurations();
|
||||
}
|
||||
|
||||
export default seedAdminConfigurations;
|
||||
|
||||
@ -18,30 +18,19 @@ const startServer = async (): Promise<void> => {
|
||||
// Seed default configurations if table is empty
|
||||
try {
|
||||
await seedDefaultConfigurations();
|
||||
// console.log('⚙️ System configurations initialized');
|
||||
} catch (error) {
|
||||
console.warn('⚠️ Configuration seeding skipped');
|
||||
console.error('⚠️ Configuration seeding error:', error);
|
||||
}
|
||||
|
||||
// Initialize holidays cache for TAT calculations
|
||||
try {
|
||||
await initializeHolidaysCache();
|
||||
console.log('📅 Holiday calendar loaded for TAT calculations');
|
||||
} catch (error) {
|
||||
console.warn('⚠️ Holiday calendar not loaded - TAT will use weekends only');
|
||||
// Silently fall back to weekends-only TAT calculation
|
||||
}
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`🚀 Server running on port ${PORT}`);
|
||||
console.log(`📊 Environment: ${process.env.NODE_ENV || 'development'}`);
|
||||
console.log(`🌐 API Base URL: http://localhost:${PORT}`);
|
||||
console.log(`❤️ Health Check: http://localhost:${PORT}/health`);
|
||||
console.log(`🔌 Socket.IO path: /socket.io`);
|
||||
console.log(`⏰ TAT Worker: Initialized and listening`);
|
||||
console.log('');
|
||||
logSystemConfig(); // Log centralized system configuration
|
||||
console.log('');
|
||||
logTatConfig(); // Log TAT-specific details
|
||||
console.log(`🚀 Server running on port ${PORT} | ${process.env.NODE_ENV || 'development'}`);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ Unable to start server:', error);
|
||||
|
||||
@ -15,7 +15,7 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
);
|
||||
|
||||
if (count && (count[0] as any).count > 0) {
|
||||
logger.info('[Config Seed] Configurations already exist. Skipping seed.');
|
||||
// Table has data, skip seeding silently
|
||||
return;
|
||||
}
|
||||
|
||||
@ -26,8 +26,8 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
INSERT INTO admin_configurations (
|
||||
config_id, config_key, config_category, config_value, value_type,
|
||||
display_name, description, default_value, is_editable, is_sensitive,
|
||||
validation_rules, ui_component, sort_order, requires_restart,
|
||||
created_at, updated_at
|
||||
validation_rules, ui_component, options, sort_order, requires_restart,
|
||||
last_modified_by, last_modified_at, created_at, updated_at
|
||||
) VALUES
|
||||
-- TAT Settings
|
||||
(
|
||||
@ -43,8 +43,11 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
false,
|
||||
'{"min": 1, "max": 168}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
1,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -61,8 +64,11 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
false,
|
||||
'{"min": 1, "max": 720}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
2,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -76,9 +82,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Send first gentle reminder when this percentage of TAT is elapsed',
|
||||
'50',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'slider',
|
||||
NULL,
|
||||
3,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -92,9 +103,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Send escalation warning when this percentage of TAT is elapsed',
|
||||
'75',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'slider',
|
||||
NULL,
|
||||
4,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -108,9 +124,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Hour when working day starts (24-hour format, 0-23)',
|
||||
'9',
|
||||
true,
|
||||
false,
|
||||
'{"min": 0, "max": 23}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
5,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -124,9 +145,56 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Hour when working day ends (24-hour format, 0-23)',
|
||||
'18',
|
||||
true,
|
||||
false,
|
||||
'{"min": 0, "max": 23}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
6,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'WORK_START_DAY',
|
||||
'TAT_SETTINGS',
|
||||
'1',
|
||||
'NUMBER',
|
||||
'Working Week Start Day',
|
||||
'Day of week start (1=Monday, 7=Sunday)',
|
||||
'1',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 7}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
7,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'WORK_END_DAY',
|
||||
'TAT_SETTINGS',
|
||||
'5',
|
||||
'NUMBER',
|
||||
'Working Week End Day',
|
||||
'Day of week end (1=Monday, 7=Sunday)',
|
||||
'5',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 7}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
8,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -141,9 +209,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Maximum allowed file size for document uploads in megabytes',
|
||||
'10',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
10,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -157,9 +230,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Comma-separated list of allowed file extensions for uploads',
|
||||
'pdf,doc,docx,xls,xlsx,ppt,pptx,jpg,jpeg,png,gif',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'text',
|
||||
NULL,
|
||||
11,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -173,9 +251,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Number of days to retain documents after workflow closure before archival',
|
||||
'365',
|
||||
true,
|
||||
false,
|
||||
'{"min": 30, "max": 3650}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
12,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -190,9 +273,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Toggle AI-generated conclusion remarks for workflow closures',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
20,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -206,9 +294,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Maximum character limit for AI-generated conclusion remarks',
|
||||
'500',
|
||||
true,
|
||||
false,
|
||||
'{"min": 100, "max": 2000}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
21,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -223,9 +316,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Send email notifications for workflow events',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
30,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -239,9 +337,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Send browser push notifications for real-time events',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
31,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -255,9 +358,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Delay in milliseconds before sending batched notifications to avoid spam',
|
||||
'5000',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1000, "max": 30000}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
32,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -272,9 +380,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Display total requests KPI card on dashboard',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
40,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -288,9 +401,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Display open requests KPI card on dashboard',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
41,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -304,9 +422,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Display TAT compliance KPI card on dashboard',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
42,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -320,9 +443,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Display pending actions KPI card on dashboard',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
43,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -337,9 +465,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Enable users to add spectators to workflow requests',
|
||||
'true',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
50,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -353,9 +486,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Maximum number of spectators allowed per workflow request',
|
||||
'20',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 100}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
51,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -369,9 +507,14 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
'Allow sharing workflow links with users outside the organization',
|
||||
'false',
|
||||
true,
|
||||
false,
|
||||
'{}'::jsonb,
|
||||
'toggle',
|
||||
NULL,
|
||||
52,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
@ -379,38 +522,48 @@ export async function seedDefaultConfigurations(): Promise<void> {
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'MAX_APPROVAL_LEVELS',
|
||||
'WORKFLOW_LIMITS',
|
||||
'SYSTEM_SETTINGS',
|
||||
'10',
|
||||
'NUMBER',
|
||||
'Maximum Approval Levels',
|
||||
'Maximum number of approval levels allowed per workflow',
|
||||
'10',
|
||||
true,
|
||||
false,
|
||||
'{"min": 1, "max": 20}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
60,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
gen_random_uuid(),
|
||||
'MAX_PARTICIPANTS_PER_REQUEST',
|
||||
'WORKFLOW_LIMITS',
|
||||
'SYSTEM_SETTINGS',
|
||||
'50',
|
||||
'NUMBER',
|
||||
'Maximum Participants per Request',
|
||||
'Maximum total participants (approvers + spectators) per workflow',
|
||||
'50',
|
||||
true,
|
||||
false,
|
||||
'{"min": 2, "max": 200}'::jsonb,
|
||||
'number',
|
||||
NULL,
|
||||
61,
|
||||
false,
|
||||
NULL,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW()
|
||||
)
|
||||
`, { type: QueryTypes.INSERT });
|
||||
|
||||
logger.info('[Config Seed] ✅ Default configurations seeded successfully (18 settings across 7 categories)');
|
||||
logger.info('[Config Seed] ✅ Default configurations seeded successfully (20 settings across 7 categories)');
|
||||
} catch (error) {
|
||||
logger.error('[Config Seed] Error seeding configurations:', error);
|
||||
// Don't throw - let server start even if seeding fails
|
||||
|
||||
@ -39,9 +39,8 @@ async function loadWorkingHoursCache(): Promise<void> {
|
||||
};
|
||||
workingHoursCacheExpiry = dayjs().add(5, 'minute').toDate();
|
||||
|
||||
console.log(`[TAT Utils] Loaded working hours: ${hours.startHour}:00-${hours.endHour}:00, Days: ${startDay}-${endDay}`);
|
||||
} catch (error) {
|
||||
console.error('[TAT Utils] Error loading working hours cache:', error);
|
||||
console.error('[TAT] Error loading working hours:', error);
|
||||
// Fallback to default values from TAT_CONFIG
|
||||
workingHoursCache = {
|
||||
startHour: TAT_CONFIG.WORK_START_HOUR,
|
||||
@ -72,9 +71,8 @@ async function loadHolidaysCache(): Promise<void> {
|
||||
holidaysCache = new Set(holidays);
|
||||
holidaysCacheExpiry = dayjs().add(6, 'hour').toDate();
|
||||
|
||||
console.log(`[TAT Utils] Loaded ${holidays.length} holidays into cache`);
|
||||
} catch (error) {
|
||||
console.error('[TAT Utils] Error loading holidays cache:', error);
|
||||
console.error('[TAT] Error loading holidays:', error);
|
||||
// Continue without holidays if loading fails
|
||||
}
|
||||
}
|
||||
@ -226,7 +224,7 @@ export async function initializeHolidaysCache(): Promise<void> {
|
||||
export function clearWorkingHoursCache(): void {
|
||||
workingHoursCache = null;
|
||||
workingHoursCacheExpiry = null;
|
||||
console.log('[TAT Utils] Working hours cache cleared');
|
||||
// Cache cleared
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user