Validation System
Data Validation System
Section titled “Data Validation System”A comprehensive, modular validation system for MES data with rich logging, HTTP status codes, and user-friendly messages.
Features
Section titled “Features”- ✅ Modular validators - Separate validator for each entity type
- ✅ FK/PK validation - Validates all foreign key relationships before insertion
- ✅ Rich logging - Console logs with HTTP status codes (200, 400, 422, etc.)
- ✅ User-friendly messages - Toast-ready messages for UI feedback
- ✅ API-ready - Format responses for RESTful APIs
- ✅ Type-safe - Full TypeScript support
Quick Start
Section titled “Quick Start”Basic Usage
Section titled “Basic Usage”import { ValidationContext, ValidationLogger, ValidatorFactory,} from "@/lib/validation";
// Create validation context with available IDsconst context: ValidationContext = { tenantId: "your-tenant-id", validJobIds: ["job-id-1", "job-id-2"], validPartIds: ["part-id-1", "part-id-2"], validCellIds: ["cell-id-1", "cell-id-2"], // ... other valid IDs};
// Create loggerconst logger = new ValidationLogger();
// Get validator for your entity typeconst validator = ValidatorFactory.getValidator("operations");
// Validate your dataconst result = validator.validateBatch(operations, context);
// Log the resultlogger.logValidation(result, "operations");
// Check if validation passedif (!result.valid) { console.error("Validation failed:", result.errors); throw new Error(result.summary);}
// Insert data if validawait supabase.from("operations").insert(operations);Mock Data Generation Example
Section titled “Mock Data Generation Example”import { generateMockData } from "@/lib/mockDataGenerator";
// The mock generator now uses validation internallyconst result = await generateMockData(tenantId);
if (result.success) { console.log("✓ Mock data created and validated");} else { console.error("✗ Validation failed:", result.error);}Available Validators
Section titled “Available Validators”CellValidator- Validates manufacturing cellsJobValidator- Validates jobs/work ordersPartValidator- Validates parts (includes parent_part_id FK check)OperationValidator- Validates operationsTimeEntryValidator- Validates time tracking entriesQuantityRecordValidator- Validates quantity/scrap recordsIssueValidator- Validates issues/NCRsOperationResourceValidator- Validates operation-resource links
Validation Context
Section titled “Validation Context”The ValidationContext object contains all valid IDs for FK validation:
interface ValidationContext { validJobIds?: string[]; // For parts.job_id validPartIds?: string[]; // For operations.part_id, parts.parent_part_id validCellIds?: string[]; // For operations.cell_id validOperationIds?: string[]; // For time_entries.operation_id, issues.operation_id validOperatorIds?: string[]; // For time_entries.operator_id, issues.created_by validResourceIds?: string[]; // For operation_resources.resource_id validScrapReasonIds?: string[]; // For quantity_records.scrap_reason_id tenantId: string; // Required tenant ID}Validation Results
Section titled “Validation Results”Each validation returns a ValidationResult:
interface ValidationResult { valid: boolean; // Overall validation status severity: ValidationSeverity; // ERROR | WARNING | INFO httpStatus: number; // 200 OK | 422 Unprocessable Entity | 400 Bad Request errors: ValidationError[]; // Array of validation errors warnings: ValidationWarning[]; // Array of warnings summary: string; // User-friendly summary (for toasts) technicalDetails: string; // Detailed technical log message}HTTP Status Codes
Section titled “HTTP Status Codes”The validation system uses proper HTTP status codes:
200 OK- Validation passed400 Bad Request- Invalid data format (e.g., not an array)422 Unprocessable Entity- Validation errors (FK violations, type mismatches, etc.)
Error Types
Section titled “Error Types”Each validation error includes a constraint type:
NOT_NULL- Required field is missingFK_CONSTRAINT- Foreign key references non-existent recordFK_REQUIRED- Required foreign key is missingUUID_FORMAT- Invalid UUID formatTYPE_MISMATCH- Wrong data type (e.g., string instead of number)MIN_VALUE- Numeric value below minimumMAX_VALUE- Numeric value above maximum
Logging
Section titled “Logging”The ValidationLogger provides rich console logging:
const logger = new ValidationLogger();
// Log validation resultslogger.logValidation(result, "operations");
// Get summaryconst summary = logger.getSummary();// { totalValidations: 5, passed: 4, failed: 1, warnings: 0 }
// Get toast messageconst toast = logger.getToastMessage();// { title: "...", description: "...", variant: "destructive" | "success" }
// Get all logsconst logs = logger.getLogs();API Response Formatting
Section titled “API Response Formatting”For RESTful APIs, use APIResponseFormatter:
import { APIResponseFormatter } from "@/lib/validation";
// Format single validationconst response = APIResponseFormatter.formatResponse(result, "CREATE");// {// status: 422,// success: false,// message: "Validation failed",// errors: [...],// data: undefined// }
// Format batch operationsconst batchResponse = APIResponseFormatter.formatBatchResponse(results, "CREATE");// {// status: 200,// success: true,// summary: { total: 10, successful: 10, failed: 0 },// results: [...]// }Example: Validating Operations Before Insert
Section titled “Example: Validating Operations Before Insert”import { ValidationContext, ValidationLogger, OperationValidator,} from "@/lib/validation";
async function insertOperations(operations: any[], tenantId: string) { // Fetch valid IDs from database const { data: parts } = await supabase .from("parts") .select("id") .eq("tenant_id", tenantId);
const { data: cells } = await supabase .from("cells") .select("id") .eq("tenant_id", tenantId);
// Build validation context const context: ValidationContext = { tenantId, validPartIds: parts?.map((p) => p.id) || [], validCellIds: cells?.map((c) => c.id) || [], };
// Validate const logger = new ValidationLogger(); const validator = new OperationValidator(); const result = validator.validateBatch(operations, context);
logger.logValidation(result, "operations");
if (!result.valid) { throw new Error(result.summary); }
// Insert if valid const { error } = await supabase.from("operations").insert(operations);
if (error) throw error;
return { success: true, count: operations.length };}Best Practices
Section titled “Best Practices”- Always validate before insert - Catch errors early with clear messages
- Build proper context - Include all valid IDs for FK validation
- Use the logger - Rich console output helps debugging
- Handle validation errors gracefully - Show user-friendly messages in UI
- Log validation results - Track what was validated and what failed
Future Extensions
Section titled “Future Extensions”This validation system can be extended for:
- ✨ Custom validation rules per tenant
- ✨ Async validation with database lookups
- ✨ Validation caching for performance
- ✨ Webhook notifications on validation failures
- ✨ Validation history tracking