import logger from '@utils/logger'; // Special UUID for system events (login, etc.) - well-known UUID: 00000000-0000-0000-0000-000000000001 export const SYSTEM_EVENT_REQUEST_ID = '00000000-0000-0000-0000-000000000001'; export type ActivityEntry = { requestId: string; type: 'created' | 'submitted' | 'assignment' | 'approval' | 'rejection' | 'status_change' | 'comment' | 'reminder' | 'document_added' | 'sla_warning' | 'ai_conclusion_generated' | 'summary_generated' | 'closed' | 'login' | 'paused' | 'resumed' | 'pause_retriggered'; user?: { userId: string; name?: string; email?: string }; timestamp: string; action: string; details: string; metadata?: any; ipAddress?: string; userAgent?: string; category?: string; severity?: string; }; class ActivityService { private byRequest: Map = new Map(); private inferCategory(type: string): string { const categoryMap: Record = { 'created': 'WORKFLOW', 'submitted': 'WORKFLOW', 'approval': 'WORKFLOW', 'rejection': 'WORKFLOW', 'status_change': 'WORKFLOW', 'assignment': 'WORKFLOW', 'comment': 'COLLABORATION', 'document_added': 'DOCUMENT', 'sla_warning': 'SYSTEM', 'reminder': 'SYSTEM', 'ai_conclusion_generated': 'SYSTEM', 'closed': 'WORKFLOW', 'login': 'AUTHENTICATION', 'paused': 'WORKFLOW', 'resumed': 'WORKFLOW', 'pause_retriggered': 'WORKFLOW' }; return categoryMap[type] || 'OTHER'; } private inferSeverity(type: string): string { const severityMap: Record = { 'rejection': 'WARNING', 'sla_warning': 'WARNING', 'approval': 'INFO', 'closed': 'INFO', 'status_change': 'INFO', 'login': 'INFO', 'created': 'INFO', 'submitted': 'INFO', 'comment': 'INFO', 'document_added': 'INFO', 'assignment': 'INFO', 'reminder': 'INFO', 'ai_conclusion_generated': 'INFO', 'paused': 'WARNING', 'resumed': 'INFO', 'pause_retriggered': 'INFO' }; return severityMap[type] || 'INFO'; } async log(entry: ActivityEntry) { const list = this.byRequest.get(entry.requestId) || []; list.push(entry); this.byRequest.set(entry.requestId, list); // Persist to database try { const { Activity } = require('@models/Activity'); const userName = entry.user?.name || entry.user?.email || null; const activityData = { requestId: entry.requestId, userId: entry.user?.userId || null, userName: userName, activityType: entry.type, activityDescription: entry.details, activityCategory: entry.category || this.inferCategory(entry.type), severity: entry.severity || this.inferSeverity(entry.type), metadata: entry.metadata || null, isSystemEvent: !entry.user, ipAddress: entry.ipAddress || null, // Database accepts null userAgent: entry.userAgent || null, // Database accepts null }; logger.info(`[Activity] Creating activity:`, { requestId: entry.requestId, userName, userId: entry.user?.userId, type: entry.type, ipAddress: entry.ipAddress ? '***' : null }); await Activity.create(activityData); logger.info(`[Activity] Successfully logged activity for request ${entry.requestId} by user: ${userName}`); } catch (error) { logger.error('[Activity] Failed to persist activity:', error); } } get(requestId: string): ActivityEntry[] { return this.byRequest.get(requestId) || []; } } export const activityService = new ActivityService();