CR Fixed for mand for varience

This commit is contained in:
Malini 2026-02-13 12:12:34 +05:30
parent 81f8ef2081
commit 11392873c3
2 changed files with 182 additions and 3 deletions

View File

@ -1170,6 +1170,53 @@ useEffect(() => {
});
};
// Calculate percentage variation between previous and current quarter costs
const calculateVariationPercentage = (product) => {
// Previous quarter costs (Q4): October, November, December
const previousCosts = [
parseFloat(product.octCost) || 0,
parseFloat(product.novCost) || 0,
parseFloat(product.decCost) || 0
];
// Current quarter costs (Q1): January, February, March
const currentCosts = [
parseFloat(product.janCost) || 0,
parseFloat(product.febCost) || 0,
parseFloat(product.marCost) || 0
];
const totalPreviousCost = previousCosts.reduce((sum, cost) => sum + cost, 0);
const totalCurrentCost = currentCosts.reduce((sum, cost) => sum + cost, 0);
// If previous cost is 0, return 0 to avoid division by zero
if (totalPreviousCost === 0) {
console.log('🔍 Variation Calculation: Previous cost is 0, returning 0% variation');
return 0;
}
// Calculate percentage variation
const variation = ((totalCurrentCost - totalPreviousCost) / totalPreviousCost) * 100;
console.log('🔍 Variation Calculation Details:', {
productId: product.id || 'unknown',
previousCosts,
currentCosts,
totalPreviousCost,
totalCurrentCost,
variation: variation.toFixed(2) + '%',
isMandatory: Math.abs(variation) > 10
});
return variation;
};
// Check if variation reason should be mandatory based on variation percentage
const isVariationReasonMandatory = (product) => {
const variation = calculateVariationPercentage(product);
return Math.abs(variation) > 10; // Greater than +10% or less than -10%
};
// Simple validation function
const validateField = (fieldName, value, productIndex) => {
const errors = { ...formErrors };
@ -1244,6 +1291,28 @@ useEffect(() => {
isValid = false;
}
});
// Dynamic validation for variation reason based on cost variation
const mandatoryVariationReason = isVariationReasonMandatory(product);
if (mandatoryVariationReason) {
// Check if variation reason is selected
if (!product.variationReason || product.variationReason === '0' || product.variationReason === '') {
errors[`variationReason_${index}`] = 'Reason for variation is required when cost variation exceeds ±10%';
isValid = false;
}
// If "Other" is selected, validate the other variation reason field
const selectedReason = variationReasons.find(r => r.value === product.variationReason);
const isOtherSelected = selectedReason && (
(selectedReason.name && selectedReason.name.toLowerCase().includes('other')) ||
(selectedReason.label && selectedReason.label.toLowerCase().includes('other'))
);
if (isOtherSelected && (!product.otherVariationReason || product.otherVariationReason.trim() === '')) {
errors[`otherVariationReason_${index}`] = 'Please specify the reason for variation';
isValid = false;
}
}
});
setFormErrors(errors);
@ -1636,6 +1705,102 @@ useEffect(() => {
delete newErrors[errorKey];
setFormErrors(newErrors);
}
// Real-time validation for variation reason when cost fields change
const costFields = ['octCost', 'novCost', 'decCost', 'janCost', 'febCost', 'marCost'];
if (costFields.includes(field)) {
const updatedProduct = updatedProducts.find(p => p.id === id);
if (updatedProduct) {
const mandatoryVariationReason = isVariationReasonMandatory(updatedProduct);
const variationErrorKey = `variationReason_${productIndex}`;
const otherVariationErrorKey = `otherVariationReason_${productIndex}`;
const newErrors = { ...formErrors };
if (mandatoryVariationReason) {
// Check if variation reason is selected
if (!updatedProduct.variationReason || updatedProduct.variationReason === '0' || updatedProduct.variationReason === '') {
newErrors[variationErrorKey] = 'Reason for variation is required when cost variation exceeds ±10%';
} else {
delete newErrors[variationErrorKey];
// If "Other" is selected, validate the other variation reason field
const selectedReason = variationReasons.find(r => r.value === updatedProduct.variationReason);
const isOtherSelected = selectedReason && (
(selectedReason.name && selectedReason.name.toLowerCase().includes('other')) ||
(selectedReason.label && selectedReason.label.toLowerCase().includes('other'))
);
if (isOtherSelected && (!updatedProduct.otherVariationReason || updatedProduct.otherVariationReason.trim() === '')) {
newErrors[otherVariationErrorKey] = 'Please specify the reason for variation';
} else {
delete newErrors[otherVariationErrorKey];
}
}
} else {
// Remove variation reason errors if variation is within ±10%
delete newErrors[variationErrorKey];
delete newErrors[otherVariationErrorKey];
}
setFormErrors(newErrors);
}
}
// Real-time validation when variation reason field changes
if (field === 'variationReason' || field === 'otherVariationReason') {
const updatedProduct = updatedProducts.find(p => p.id === id);
if (updatedProduct) {
const mandatoryVariationReason = isVariationReasonMandatory(updatedProduct);
const variationErrorKey = `variationReason_${productIndex}`;
const otherVariationErrorKey = `otherVariationReason_${productIndex}`;
const newErrors = { ...formErrors };
if (mandatoryVariationReason) {
if (field === 'variationReason') {
// Check if variation reason is selected
if (!updatedProduct.variationReason || updatedProduct.variationReason === '0' || updatedProduct.variationReason === '') {
newErrors[variationErrorKey] = 'Reason for variation is required when cost variation exceeds ±10%';
} else {
delete newErrors[variationErrorKey];
// If "Other" is selected, validate the other variation reason field
const selectedReason = variationReasons.find(r => r.value === updatedProduct.variationReason);
const isOtherSelected = selectedReason && (
(selectedReason.name && selectedReason.name.toLowerCase().includes('other')) ||
(selectedReason.label && selectedReason.label.toLowerCase().includes('other'))
);
if (isOtherSelected && (!updatedProduct.otherVariationReason || updatedProduct.otherVariationReason.trim() === '')) {
newErrors[otherVariationErrorKey] = 'Please specify the reason for variation';
} else {
delete newErrors[otherVariationErrorKey];
}
}
} else if (field === 'otherVariationReason') {
// Validate other variation reason if "Other" is selected
const selectedReason = variationReasons.find(r => r.value === updatedProduct.variationReason);
const isOtherSelected = selectedReason && (
(selectedReason.name && selectedReason.name.toLowerCase().includes('other')) ||
(selectedReason.label && selectedReason.label.toLowerCase().includes('other'))
);
if (isOtherSelected && (!updatedProduct.otherVariationReason || updatedProduct.otherVariationReason.trim() === '')) {
newErrors[otherVariationErrorKey] = 'Please specify the reason for variation';
} else {
delete newErrors[otherVariationErrorKey];
}
}
} else {
// Remove variation reason errors if variation is within ±10%
delete newErrors[variationErrorKey];
delete newErrors[otherVariationErrorKey];
}
setFormErrors(newErrors);
}
}
}
onProductsChange(updatedProducts);
@ -2397,13 +2562,20 @@ useEffect(() => {
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Reason for Variation</label>
<label className="block text-sm font-medium text-gray-700 mb-1">
Reason for Variation
{isVariationReasonMandatory(p) && <span className="text-red-600">*</span>}
</label>
<Select
placeholder={isLoadingReasons ? 'Loading reasons...' : 'Select reason'}
options={variationReasons}
value={p.variationReason || ''}
onChange={(e) => updateProductField(p.id, 'variationReason', e.target.value, variationReasons)}
error={!!formErrors[`variationReason_${idx}`]}
/>
{formErrors[`variationReason_${idx}`] && (
<p className="mt-1 text-xs text-red-600">{formErrors[`variationReason_${idx}`]}</p>
)}
{(showOtherVariationReason[p.id] || (p.variationReason && (p.variationReason.toString().toLowerCase().includes('other') || (variationReasons.find(r => r.value === p.variationReason)?.name?.toLowerCase().includes('other') || variationReasons.find(r => r.value === p.variationReason)?.label?.toLowerCase().includes('other'))))) && (
<div className="mt-3 p-3 bg-gray-50 rounded-md border border-gray-200">
<label className="block text-sm font-medium text-gray-700 mb-2">Please specify the reason</label>
@ -2412,7 +2584,11 @@ useEffect(() => {
placeholder="Enter your reason here..."
value={p.otherVariationReason || ''}
onChange={(e) => updateProductField(p.id, 'otherVariationReason', e.target.value)}
error={!!formErrors[`otherVariationReason_${idx}`]}
/>
{formErrors[`otherVariationReason_${idx}`] && (
<p className="mt-1 text-xs text-red-600">{formErrors[`otherVariationReason_${idx}`]}</p>
)}
{/* <p className="mt-1 text-xs text-gray-500">Please provide details about the variation reason</p> */}
</div>
)}

View File

@ -4,7 +4,8 @@ import {
IconButton,
Dialog,
DialogTitle,
DialogContent
DialogContent,
Tooltip
} from '@mui/material';
import { SelectField as BaseSelectField } from '@/components/common/FormControls';
import Table from '@/components/common/Table';
@ -513,7 +514,9 @@ const ManufacturingIndex = () => {
Next scheduled run: {nextScheduledRun}
</div>
<div className="flex text-sm text-gray-600">
<InfoOutlinedIcon className="text-gray-400 text-base mr-1 mt-0.5 flex-shrink-0" />
<Tooltip title="Manufacturing index calculation method" arrow>
<InfoOutlinedIcon className="text-gray-400 text-sm mr-1 align-middle flex-shrink-0 mt-[-0.2rem]" />
</Tooltip>
<span className="whitespace-nowrap">Formula: Manufacturing index<sub>t</sub> = Σ (sector weight<sub>i</sub> × group index<sub>i,t</sub>)</span>
</div>
</div>