import { sequelize } from '@config/database'; import { QueryTypes } from 'sequelize'; import logger from '@utils/logger'; /** * Seed default admin configurations if table is empty * Called automatically on server startup */ export async function seedDefaultConfigurations(): Promise { try { // Check if configurations already exist const count = await sequelize.query( 'SELECT COUNT(*) as count FROM admin_configurations', { type: QueryTypes.SELECT } ); if (count && (count[0] as any).count > 0) { // Table has data, skip seeding silently return; } logger.info('[Config Seed] Seeding default configurations...'); // Insert 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, options, sort_order, requires_restart, last_modified_by, last_modified_at, 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', NULL, 1, false, NULL, NULL, 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 days only, excludes weekends and holidays)', '48', true, false, '{"min": 1, "max": 720}'::jsonb, 'number', NULL, 2, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'TAT_REMINDER_THRESHOLD_1', 'TAT_SETTINGS', '50', 'NUMBER', 'First TAT Reminder Threshold (%)', '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() ), ( gen_random_uuid(), 'TAT_REMINDER_THRESHOLD_2', 'TAT_SETTINGS', '75', 'NUMBER', 'Second TAT Reminder Threshold (%)', '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() ), ( gen_random_uuid(), 'WORK_START_HOUR', 'TAT_SETTINGS', '9', 'NUMBER', 'Working Day Start Hour', '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() ), ( gen_random_uuid(), 'WORK_END_HOUR', 'TAT_SETTINGS', '18', 'NUMBER', 'Working Day End Hour', '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() ), -- Document Policy ( gen_random_uuid(), 'MAX_FILE_SIZE_MB', 'DOCUMENT_POLICY', '10', 'NUMBER', 'Maximum File Upload Size (MB)', '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() ), ( gen_random_uuid(), 'ALLOWED_FILE_TYPES', 'DOCUMENT_POLICY', 'pdf,doc,docx,xls,xlsx,ppt,pptx,jpg,jpeg,png,gif', 'STRING', 'Allowed File Types', '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() ), ( gen_random_uuid(), 'DOCUMENT_RETENTION_DAYS', 'DOCUMENT_POLICY', '365', 'NUMBER', 'Document Retention Period (Days)', '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() ), -- AI Configuration ( gen_random_uuid(), 'AI_REMARK_GENERATION_ENABLED', 'AI_CONFIGURATION', 'true', 'BOOLEAN', 'Enable AI Remark Generation', 'Toggle AI-generated conclusion remarks for workflow closures', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 20, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'AI_REMARK_MAX_CHARACTERS', 'AI_CONFIGURATION', '500', 'NUMBER', 'AI Remark Maximum Characters', 'Maximum character limit for AI-generated conclusion remarks', '500', true, false, '{"min": 100, "max": 2000}'::jsonb, 'number', NULL, 21, false, NULL, NULL, NOW(), NOW() ), -- Notification Rules ( gen_random_uuid(), 'ENABLE_EMAIL_NOTIFICATIONS', 'NOTIFICATION_RULES', 'true', 'BOOLEAN', 'Enable Email Notifications', 'Send email notifications for workflow events', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 30, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'ENABLE_PUSH_NOTIFICATIONS', 'NOTIFICATION_RULES', 'true', 'BOOLEAN', 'Enable Push Notifications', 'Send browser push notifications for real-time events', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 31, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'NOTIFICATION_BATCH_DELAY_MS', 'NOTIFICATION_RULES', '5000', 'NUMBER', 'Notification Batch Delay (ms)', '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() ), -- Dashboard Layout ( gen_random_uuid(), 'DASHBOARD_SHOW_TOTAL_REQUESTS', 'DASHBOARD_LAYOUT', 'true', 'BOOLEAN', 'Show Total Requests Card', 'Display total requests KPI card on dashboard', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 40, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'DASHBOARD_SHOW_OPEN_REQUESTS', 'DASHBOARD_LAYOUT', 'true', 'BOOLEAN', 'Show Open Requests Card', 'Display open requests KPI card on dashboard', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 41, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'DASHBOARD_SHOW_TAT_COMPLIANCE', 'DASHBOARD_LAYOUT', 'true', 'BOOLEAN', 'Show TAT Compliance Card', 'Display TAT compliance KPI card on dashboard', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 42, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'DASHBOARD_SHOW_PENDING_ACTIONS', 'DASHBOARD_LAYOUT', 'true', 'BOOLEAN', 'Show Pending Actions Card', 'Display pending actions KPI card on dashboard', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 43, false, NULL, NULL, NOW(), NOW() ), -- Workflow Sharing Policy ( gen_random_uuid(), 'ALLOW_ADD_SPECTATOR', 'WORKFLOW_SHARING', 'true', 'BOOLEAN', 'Allow Adding Spectators', 'Enable users to add spectators to workflow requests', 'true', true, false, '{}'::jsonb, 'toggle', NULL, 50, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'MAX_SPECTATORS_PER_REQUEST', 'WORKFLOW_SHARING', '20', 'NUMBER', 'Maximum Spectators per Request', 'Maximum number of spectators allowed per workflow request', '20', true, false, '{"min": 1, "max": 100}'::jsonb, 'number', NULL, 51, false, NULL, NULL, NOW(), NOW() ), ( gen_random_uuid(), 'ALLOW_EXTERNAL_SHARING', 'WORKFLOW_SHARING', 'false', 'BOOLEAN', 'Allow External Sharing', 'Allow sharing workflow links with users outside the organization', 'false', true, false, '{}'::jsonb, 'toggle', NULL, 52, false, NULL, NULL, NOW(), NOW() ), -- User Roles (Read-only settings for reference) ( gen_random_uuid(), 'MAX_APPROVAL_LEVELS', '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', '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 (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 } }