diff --git a/src/dealer-claim/components/request-detail/IOTab.tsx b/src/dealer-claim/components/request-detail/IOTab.tsx index 92e734b..0ea46df 100644 --- a/src/dealer-claim/components/request-detail/IOTab.tsx +++ b/src/dealer-claim/components/request-detail/IOTab.tsx @@ -70,7 +70,11 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) { const budgetTracking = apiRequest?.budgetTracking || request?.budgetTracking || {}; const budgetStatus = budgetTracking?.budgetStatus || budgetTracking?.budget_status || ''; const internalOrdersList = apiRequest?.internalOrders || apiRequest?.internal_orders || request?.internalOrders || []; - const isAdditionalBlockingNeeded = budgetStatus === 'PROPOSED' && internalOrdersList.length > 0; + const totalBlocked = useMemo(() => { + return internalOrdersList.reduce((sum: number, io: any) => sum + Number(io.ioBlockedAmount || io.io_blocked_amount || 0), 0); + }, [internalOrdersList]); + + const isAdditionalBlockingNeeded = budgetStatus === 'PROPOSED' && internalOrdersList.length > 0 && (estimatedBudget - totalBlocked) > 0.01; const [ioNumber, setIoNumber] = useState(''); const [fetchingAmount, setFetchingAmount] = useState(false); @@ -385,7 +389,14 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) { min="0" step="0.01" value={amountToBlock} - onChange={(e) => setAmountToBlock(e.target.value)} + onChange={(e) => { + const val = e.target.value; + if (parseFloat(val) < 0) { + toast.error('Amount cannot be negative'); + return; + } + setAmountToBlock(val); + }} className="pl-8" /> diff --git a/src/dealer-claim/components/request-detail/modals/DealerCompletionDocumentsModal.tsx b/src/dealer-claim/components/request-detail/modals/DealerCompletionDocumentsModal.tsx index 88a8264..6d9a2bc 100644 --- a/src/dealer-claim/components/request-detail/modals/DealerCompletionDocumentsModal.tsx +++ b/src/dealer-claim/components/request-detail/modals/DealerCompletionDocumentsModal.tsx @@ -273,8 +273,14 @@ export function DealerCompletionDocumentsModal({ if (item.id === id) { let updatedItem = { ...item, [field]: value }; - // Re-calculate GST if relevant fields change if (['amount', 'gstRate', 'cgstRate', 'sgstRate', 'utgstRate', 'igstRate', 'quantity'].includes(field)) { + // Negative amount validation + const numValue = parseFloat(value); + if (!isNaN(numValue) && numValue < 0) { + toast.error('Value cannot be negative'); + return item; + } + const amount = field === 'amount' ? parseFloat(value) || 0 : item.amount; const quantity = field === 'quantity' ? parseInt(value) || 1 : item.quantity; @@ -523,6 +529,13 @@ export function DealerCompletionDocumentsModal({ return; } + // Check for negative amounts + const hasNegativeAmounts = expenseItems.some(item => item.amount < 0 || item.quantity < 1); + if (hasNegativeAmounts) { + toast.error('Please ensure all amounts are non-negative and quantity is at least 1'); + return; + } + // Filter valid expense items const validExpenses = expenseItems.filter( (item) => item.description.trim() !== '' && item.amount > 0 diff --git a/src/dealer-claim/components/request-detail/modals/DealerProposalSubmissionModal.tsx b/src/dealer-claim/components/request-detail/modals/DealerProposalSubmissionModal.tsx index 8530d9d..78501a1 100644 --- a/src/dealer-claim/components/request-detail/modals/DealerProposalSubmissionModal.tsx +++ b/src/dealer-claim/components/request-detail/modals/DealerProposalSubmissionModal.tsx @@ -437,8 +437,14 @@ export function DealerProposalSubmissionModal({ if (item.id === id) { let updatedItem = { ...item, [field]: value }; - // Re-calculate GST if relevant fields change if (['amount', 'gstRate', 'cgstRate', 'sgstRate', 'utgstRate', 'igstRate'].includes(field)) { + // Negative amount validation + const numValue = parseFloat(value); + if (!isNaN(numValue) && numValue < 0) { + toast.error('Value cannot be negative'); + return item; + } + const amount = field === 'amount' ? parseFloat(value) || 0 : item.amount; const quantity = 1; // Quantity is now fixed to 1 @@ -524,6 +530,18 @@ export function DealerProposalSubmissionModal({ return; } + // Check for negative amounts or invalid days + const hasNegativeAmounts = costItems.some(item => item.amount < 0); + if (hasNegativeAmounts) { + toast.error('Please ensure all amounts are non-negative'); + return; + } + + if (timelineMode === 'days' && (parseInt(numberOfDays) <= 0 || isNaN(parseInt(numberOfDays)))) { + toast.error('Please enter a valid number of days greater than 0'); + return; + } + // Calculate final completion date if using days mode let finalCompletionDate: string = expectedCompletionDate || ''; if (timelineMode === 'days' && numberOfDays) {