import { z } from 'zod'; // Simplified approval level schema - only requires email and tatHours // Backend will enrich with user details (approverId, approverName, levelName) const simplifiedApprovalLevelSchema = z.object({ email: z.string().email('Valid email is required'), tatHours: z.number().positive('TAT hours must be positive'), isFinalApprover: z.boolean().optional(), // Optional fields that backend will auto-populate if not provided levelNumber: z.number().int().min(1).max(10).optional(), levelName: z.string().optional(), approverId: z.string().uuid().optional(), approverEmail: z.string().email().optional(), approverName: z.string().optional(), }); // Simplified spectator schema - only requires email const simplifiedSpectatorSchema = z.object({ email: z.string().email('Valid email is required').optional(), // Optional fields that backend will auto-populate if not provided userId: z.string().uuid().optional(), userEmail: z.string().email().optional(), userName: z.string().optional(), participantType: z.enum(['INITIATOR', 'APPROVER', 'SPECTATOR'] as const).optional(), canComment: z.boolean().optional(), canViewDocuments: z.boolean().optional(), canDownloadDocuments: z.boolean().optional(), notificationEnabled: z.boolean().optional(), }); export const createWorkflowSchema = z.object({ templateType: z.enum(['CUSTOM', 'TEMPLATE']), title: z.string().min(1, 'Title is required').max(500, 'Title too long'), description: z.string().min(1, 'Description is required'), priority: z.enum(['STANDARD', 'EXPRESS'] as const), approvalLevels: z.array(simplifiedApprovalLevelSchema) .min(1, 'At least one approval level is required') .max(10, 'Maximum 10 approval levels allowed'), participants: z.array(simplifiedSpectatorSchema).optional(), spectators: z.array(simplifiedSpectatorSchema).optional(), // Alias for participants // Additional frontend compatibility fields approverCount: z.number().optional(), approvers: z.array(z.any()).optional(), priorityUi: z.string().optional(), templateId: z.string().optional(), ccList: z.array(z.any()).optional(), isDraft: z.boolean().optional(), }); export const updateWorkflowSchema = z.object({ title: z.string().min(1).max(500).optional(), description: z.string().min(1).optional(), priority: z.enum(['STANDARD', 'EXPRESS'] as const).optional(), status: z.enum(['DRAFT', 'PENDING', 'APPROVED', 'REJECTED', 'CLOSED', 'PAUSED'] as const).optional(), conclusionRemark: z.string().optional(), // For draft updates - allow updating approval levels and participants approvalLevels: z.array(z.object({ levelNumber: z.number().int().min(1).max(10), levelName: z.string().optional(), approverId: z.string().uuid(), approverEmail: z.string().email(), approverName: z.string().min(1), tatHours: z.number().positive(), isFinalApprover: z.boolean().optional(), })).optional(), participants: z.array(z.object({ userId: z.string().uuid(), userEmail: z.string().email(), userName: z.string().min(1), participantType: z.enum(['INITIATOR', 'APPROVER', 'SPECTATOR'] as const), canComment: z.boolean().optional(), canViewDocuments: z.boolean().optional(), canDownloadDocuments: z.boolean().optional(), notificationEnabled: z.boolean().optional(), })).optional(), deleteDocumentIds: z.array(z.string().uuid()).optional(), isDraft: z.boolean().optional(), }); // Helper to validate UUID or requestNumber format // Supports both old format (REQ-YYYY-NNNNN) and new format (REQ-YYYY-MM-XXXX) const workflowIdValidator = z.string().refine( (val) => { // Check if it's a valid UUID const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; if (uuidRegex.test(val)) { return true; } // Check if it's a valid requestNumber format // Old format: REQ-YYYY-NNNNN (e.g., REQ-2025-12057) - 5+ digits after year // New format: REQ-YYYY-MM-XXXX (e.g., REQ-2025-11-0001) - 2-digit month, 4-digit counter const oldFormatRegex = /^REQ-\d{4}-\d{5,}$/i; // Old: REQ-2025-12057 const newFormatRegex = /^REQ-\d{4}-\d{2}-\d{4}$/i; // New: REQ-2025-11-0001 if (oldFormatRegex.test(val) || newFormatRegex.test(val)) { return true; } return false; }, { message: 'Invalid workflow ID - must be a valid UUID or requestNumber (e.g., REQ-2025-11-0001 or REQ-2025-12057)', } ); export const workflowParamsSchema = z.object({ id: workflowIdValidator, }); export const workflowQuerySchema = z.object({ page: z.string().transform(Number).pipe(z.number().int().min(1)).optional(), limit: z.string().transform(Number).pipe(z.number().int().min(1).max(100)).optional(), status: z.enum(['DRAFT', 'PENDING', 'APPROVED', 'REJECTED', 'CLOSED', 'PAUSED'] as const).optional(), priority: z.enum(['STANDARD', 'EXPRESS'] as const).optional(), sortBy: z.string().optional(), sortOrder: z.enum(['ASC', 'DESC'] as const).optional(), }); export const validateCreateWorkflow = (data: any) => { return createWorkflowSchema.parse(data); }; export const validateUpdateWorkflow = (data: any) => { return updateWorkflowSchema.parse(data); };