validator.ts•3.45 kB
import { MRPInput, ValidationResult, ValidationMessage } from './types';
export function validateMRPInput(input: MRPInput): ValidationResult {
const messages: ValidationMessage[] = [];
// Required fields validation
if (!input.sku_location?.sku || !input.sku_location?.location) {
messages.push({
type: 'ERROR',
message: 'SKU and location are required'
});
}
// Numeric validations
if (input.must_order_point < 0) {
messages.push({
type: 'ERROR',
message: 'Must-order point cannot be negative'
});
}
if (input.current_balance < 0) {
messages.push({
type: 'WARNING',
message: 'Current balance is negative'
});
}
// Date validations
try {
const analysisDate = new Date(input.analysis_date);
const firstDelivery = new Date(input.delivery_schedule.first_delivery);
const secondDelivery = new Date(input.delivery_schedule.second_delivery);
if (firstDelivery <= analysisDate) {
messages.push({
type: 'ERROR',
message: 'First delivery date must be after analysis date'
});
}
if (secondDelivery <= firstDelivery) {
messages.push({
type: 'ERROR',
message: 'Second delivery date must be after first delivery date'
});
}
} catch (e) {
messages.push({
type: 'ERROR',
message: 'Invalid date format. Use ISO 8601 format (YYYY-MM-DD)'
});
}
// Forecast period validations
if (!input.forecast_periods || input.forecast_periods.length === 0) {
messages.push({
type: 'ERROR',
message: 'At least one forecast period is required'
});
} else {
input.forecast_periods.forEach((period, index) => {
try {
const startDate = new Date(period.start_date);
const endDate = new Date(period.end_date);
if (endDate <= startDate) {
messages.push({
type: 'ERROR',
message: `Forecast period ${index + 1}: End date must be after start date`
});
}
if (period.quantity < 0) {
messages.push({
type: 'ERROR',
message: `Forecast period ${index + 1}: Quantity cannot be negative`
});
}
} catch (e) {
messages.push({
type: 'ERROR',
message: `Forecast period ${index + 1}: Invalid date format`
});
}
});
}
// Batch size validations
if (input.batch_sizes) {
if (!input.batch_sizes.every(size => size > 0)) {
messages.push({
type: 'ERROR',
message: 'Batch sizes must be positive numbers'
});
}
if (!input.batch_sizes.every((size, i, arr) => i === 0 || size > arr[i - 1])) {
messages.push({
type: 'ERROR',
message: 'Batch sizes must be in ascending order'
});
}
}
const hasErrors = messages.some(msg => msg.type === 'ERROR');
return {
isValid: !hasErrors,
messages
};
}