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-Templatized Dealer 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-Templatized Dealer 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 */} -
- -