diff --git a/src/custom/components/ClosedRequestsFilters.tsx b/src/custom/components/ClosedRequestsFilters.tsx
index ffa98ac..17587c1 100644
--- a/src/custom/components/ClosedRequestsFilters.tsx
+++ b/src/custom/components/ClosedRequestsFilters.tsx
@@ -137,7 +137,7 @@ export function StandardClosedRequestsFilters({
All Templates
- Custom
+ Non-TemplatizedDealer Claim
diff --git a/src/custom/components/RequestsFilters.tsx b/src/custom/components/RequestsFilters.tsx
index 7ad671d..eda93bf 100644
--- a/src/custom/components/RequestsFilters.tsx
+++ b/src/custom/components/RequestsFilters.tsx
@@ -126,7 +126,7 @@ export function StandardRequestsFilters({
All Templates
- Custom
+ Non-TemplatizedDealer Claim
diff --git a/src/dealer-claim/components/request-detail/IOTab.tsx b/src/dealer-claim/components/request-detail/IOTab.tsx
index 9c4317e..f6532c3 100644
--- a/src/dealer-claim/components/request-detail/IOTab.tsx
+++ b/src/dealer-claim/components/request-detail/IOTab.tsx
@@ -10,7 +10,6 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
-import { Textarea } from '@/components/ui/textarea';
import { Badge } from '@/components/ui/badge';
import { DollarSign, Download, CircleCheckBig, Target } from 'lucide-react';
import { toast } from 'sonner';
@@ -31,7 +30,6 @@ interface IOBlockedDetails {
blockedDate: string;
blockedBy: string; // User who blocked
sapDocumentNumber: string;
- ioRemark?: string; // IO remark
status: 'blocked' | 'released' | 'failed';
}
@@ -42,7 +40,6 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
// Load existing IO data from apiRequest or request
const internalOrder = apiRequest?.internalOrder || apiRequest?.internal_order || null;
const existingIONumber = internalOrder?.ioNumber || internalOrder?.io_number || request?.ioNumber || '';
- const existingIORemark = internalOrder?.ioRemark || internalOrder?.io_remark || '';
const existingBlockedAmount = internalOrder?.ioBlockedAmount || internalOrder?.io_blocked_amount || 0;
const existingAvailableBalance = internalOrder?.ioAvailableBalance || internalOrder?.io_available_balance || 0;
const existingRemainingBalance = internalOrder?.ioRemainingBalance || internalOrder?.io_remaining_balance || 0;
@@ -51,15 +48,11 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
const organizer = internalOrder?.organizer || null;
const [ioNumber, setIoNumber] = useState(existingIONumber);
- const [ioRemark, setIoRemark] = useState(existingIORemark);
const [fetchingAmount, setFetchingAmount] = useState(false);
const [fetchedAmount, setFetchedAmount] = useState(null);
const [amountToBlock, setAmountToBlock] = useState('');
const [blockedDetails, setBlockedDetails] = useState(null);
const [blockingBudget, setBlockingBudget] = useState(false);
-
- const maxIoRemarkChars = 300;
- const ioRemarkChars = ioRemark.length;
// Load existing IO block details from apiRequest
useEffect(() => {
@@ -78,9 +71,8 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
organizer?.email ||
'Unknown User';
- // Set IO number and remark from existing data
+ // Set IO number from existing data
setIoNumber(existingIONumber);
- setIoRemark(existingIORemark);
// Only set blocked details if amount is blocked
if (existingBlockedAmount > 0) {
@@ -112,7 +104,6 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
blockedDate: internalOrder.organizedAt || internalOrder.organized_at || new Date().toISOString(),
blockedBy: blockedByName,
sapDocumentNumber: sapDocNumber,
- ioRemark: existingIORemark,
status: (internalOrder.status === 'BLOCKED' ? 'blocked' :
internalOrder.status === 'RELEASED' ? 'released' : 'blocked') as 'blocked' | 'released' | 'failed',
});
@@ -123,7 +114,7 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
}
}
}
- }, [internalOrder, existingIONumber, existingIORemark, existingBlockedAmount, existingAvailableBalance, existingRemainingBalance, sapDocNumber, organizer]);
+ }, [internalOrder, existingIONumber, existingBlockedAmount, existingAvailableBalance, existingRemainingBalance, sapDocNumber, organizer]);
/**
* Fetch available budget from SAP
@@ -166,50 +157,12 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
}
};
- /**
- * Save IO details (IO number and remark) without blocking budget
- */
- const handleSaveIODetails = async () => {
- if (!ioNumber.trim()) {
- toast.error('Please enter an IO number');
- return;
- }
-
- if (!ioRemark.trim()) {
- toast.error('Please enter an IO remark');
- return;
- }
-
- if (!requestId) {
- toast.error('Request ID not found');
- return;
- }
-
- setBlockingBudget(true);
- try {
- // Save only IO number and remark (no balance fields)
- const payload = {
- ioNumber: ioNumber.trim(),
- ioRemark: ioRemark.trim(),
- };
-
- await updateIODetails(requestId, payload);
-
- toast.success('IO details saved successfully');
-
- // Refresh request details
- onRefresh?.();
- } catch (error: any) {
- console.error('Failed to save IO details:', error);
- const errorMessage = error?.response?.data?.message || error?.message || 'Failed to save IO details';
- toast.error(errorMessage);
- } finally {
- setBlockingBudget(false);
- }
- };
-
/**
* Block budget in SAP system
+ * This function:
+ * 1. Validates the IO number and amount
+ * 2. Calls SAP to block the budget
+ * 3. Saves IO number, blocked amount, and balance details to database
*/
const handleBlockBudget = async () => {
if (!ioNumber.trim() || fetchedAmount === null) {
@@ -217,11 +170,6 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
return;
}
- if (!ioRemark.trim()) {
- toast.error('Please enter IO remark before blocking the amount');
- return;
- }
-
if (!requestId) {
toast.error('Request ID not found');
return;
@@ -234,9 +182,9 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
return;
}
- // Round to 2 decimal places to avoid floating point precision issues
- // This ensures we send clean values like 240.00 instead of 239.9999999
- const blockAmount = Math.round(blockAmountRaw * 100) / 100;
+ // Round to exactly 2 decimal places to avoid floating point precision issues
+ // Use parseFloat with toFixed to ensure exact 2 decimal precision
+ const blockAmount = parseFloat(blockAmountRaw.toFixed(2));
if (blockAmount > fetchedAmount) {
toast.error('Amount to block exceeds available IO budget');
@@ -250,12 +198,14 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
// Call updateIODetails with blockedAmount to block budget in SAP and store in database
// This will store in internal_orders and claim_budget_tracking tables
// Note: Backend will recalculate remainingBalance from SAP's response, so we pass it for reference only
+ // Ensure all amounts are rounded to 2 decimal places for consistency
+ const roundedFetchedAmount = parseFloat(fetchedAmount.toFixed(2));
+ const calculatedRemaining = parseFloat((roundedFetchedAmount - blockAmount).toFixed(2));
const payload = {
ioNumber: ioNumber.trim(),
- ioRemark: ioRemark.trim(),
- ioAvailableBalance: fetchedAmount,
+ ioAvailableBalance: roundedFetchedAmount,
ioBlockedAmount: blockAmount,
- ioRemainingBalance: fetchedAmount - blockAmount, // Calculated value (backend will use SAP's actual value)
+ ioRemainingBalance: calculatedRemaining, // Calculated value (backend will use SAP's actual value)
};
// Sending to backend
@@ -301,8 +251,6 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
currentUser?.email ||
'Current User';
- const savedIoRemark = updatedInternalOrder.ioRemark || updatedInternalOrder.io_remark || ioRemark.trim();
-
const blocked: IOBlockedDetails = {
ioNumber: updatedInternalOrder.ioNumber || updatedInternalOrder.io_number || ioNumber,
blockedAmount: savedBlockedAmount,
@@ -311,7 +259,6 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
blockedDate: updatedInternalOrder.organizedAt || updatedInternalOrder.organized_at || new Date().toISOString(),
blockedBy: blockedByName,
sapDocumentNumber: updatedInternalOrder.sapDocumentNumber || updatedInternalOrder.sap_document_number || '',
- ioRemark: savedIoRemark,
status: 'blocked',
};
@@ -371,52 +318,13 @@ export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
- {/* IO Remark Input */}
-
-
-
-
- {/* Save IO Details Button (shown when IO number is entered but amount not fetched) */}
+ {/* Instructions when IO number is entered but not fetched */}
{!fetchedAmount && !blockedDetails && ioNumber.trim() && (
-
+
+
+ Next Step: Click "Fetch Amount" to validate the IO number and get available balance from SAP.
+