Re_Backend/src/services/configSeed.service.ts
2026-03-24 20:27:28 +05:30

627 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<void> {
try {
// Ensure pgcrypto extension is available for gen_random_uuid()
try {
await sequelize.query('CREATE EXTENSION IF NOT EXISTS "pgcrypto"', { type: QueryTypes.RAW });
} catch (extError: any) {
// Extension might already exist or user might not have permission - continue
logger.debug('[Config Seed] pgcrypto extension check:', extError?.message || 'already exists');
}
logger.info('[Config Seed] Seeding default configurations (duplicates will be skipped automatically)...');
// Insert default configurations with ON CONFLICT handling
// This allows re-running the seed without errors if configs already exist
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 (Vertex AI Gemini)
(
gen_random_uuid(),
'AI_ENABLED',
'AI_CONFIGURATION',
'true',
'BOOLEAN',
'Enable AI Features',
'Master toggle to enable/disable all AI-powered features in the system',
'true',
true,
false,
'{"type": "boolean"}'::jsonb,
'toggle',
NULL,
20,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
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,
21,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'AI_MAX_REMARK_LENGTH',
'AI_CONFIGURATION',
'2000',
'NUMBER',
'AI Max Remark Length',
'Maximum character length for AI-generated conclusion remarks',
'2000',
true,
false,
'{"min": 500, "max": 5000}'::jsonb,
'number',
NULL,
24,
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,
31,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'ENABLE_IN_APP_NOTIFICATIONS',
'NOTIFICATION_RULES',
'true',
'BOOLEAN',
'Enable In-App Notifications',
'Show notifications within the application portal',
'true',
true,
false,
'{}'::jsonb,
'toggle',
NULL,
32,
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,
33,
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()
),
-- Form 16 admin (submission viewers, 26AS viewers, notifications) same admin_configurations table
(
gen_random_uuid(),
'FORM16_ADMIN_CONFIG',
'SYSTEM_SETTINGS',
'{"submissionViewerEmails":[],"twentySixAsViewerEmails":[],"reminderEnabled":true,"reminderDays":7,"notification26AsDataAdded":{"enabled":true,"template":"26AS data has been added. Please review."},"notificationForm16SuccessCreditNote":{"enabled":true,"template":"Form 16 submitted successfully. Credit note: [CreditNoteRef]."},"notificationForm16Unsuccessful":{"enabled":true,"template":"Form 16 submission was unsuccessful. Issue: [Issue]."},"alertSubmitForm16Enabled":true,"alertSubmitForm16FrequencyDays":0,"alertSubmitForm16FrequencyHours":24,"alertSubmitForm16Template":"Dear [Name], please submit Form 16A for the pending period. Due: [DueDate].","reminderNotificationEnabled":true,"reminderFrequencyDays":0,"reminderFrequencyHours":12,"reminderNotificationTemplate":"Reminder: Dear [Name], your Form 16A submission is pending for request [Request ID]. Please complete it.","debitNoteNotification":{"enabled":true,"template":"Debit note issued: [DebitNoteRef]. Please review."}}',
'JSON',
'Form 16 Admin Config',
'Form 16 visibility (submission data viewers, 26AS viewers), reminders and notification settings',
'{"submissionViewerEmails":[],"twentySixAsViewerEmails":[],"reminderEnabled":true,"reminderDays":7}',
true,
false,
'{}'::jsonb,
NULL,
NULL,
62,
false,
NULL,
NULL,
NOW(),
NOW()
)
ON CONFLICT (config_key) DO NOTHING
`, { type: QueryTypes.INSERT });
// Verify how many were actually inserted
const result = await sequelize.query(
'SELECT COUNT(*) as count FROM admin_configurations',
{ type: QueryTypes.SELECT }
);
const totalCount = result && (result[0] as any).count ? (result[0] as any).count : 0;
logger.info(`[Config Seed] ✅ Configuration seeding complete. Total configurations: ${totalCount}`);
} catch (error: any) {
logger.error('[Config Seed] ❌ Error seeding configurations:', {
message: error?.message || String(error),
stack: error?.stack,
name: error?.name
});
// Don't throw - let server start even if seeding fails
// User can manually run seed script if needed: npm run seed:config
}
}