| @@ -71,7 +71,7 @@ const InventoryLotLineTable: React.FC<Props> = ({ | |||
| const [startLocation, setStartLocation] = useState<string>(""); | |||
| const [targetLocation, setTargetLocation] = useState<number | null>(null); // Store warehouse ID instead of code | |||
| const [targetLocationInput, setTargetLocationInput] = useState<string>(""); | |||
| const [qtyToBeTransferred, setQtyToBeTransferred] = useState<number>(0); | |||
| const [qtyToBeTransferred, setQtyToBeTransferred] = useState<string>(""); | |||
| const [warehouses, setWarehouses] = useState<WarehouseResult[]>([]); | |||
| const [printModalOpen, setPrintModalOpen] = useState(false); | |||
| const [lotLineForPrint, setLotLineForPrint] = useState<InventoryLotLineResult | null>(null); | |||
| @@ -117,7 +117,18 @@ const InventoryLotLineTable: React.FC<Props> = ({ | |||
| return base.filter((line) => line.lotNo === f); | |||
| }, [inventoryLotLines, filterLotNo]); | |||
| const originalQty = selectedLotLine?.availableQty || 0; | |||
| const remainingQty = originalQty - qtyToBeTransferred; | |||
| const validatedTransferQty = useMemo(() => { | |||
| const raw = (qtyToBeTransferred ?? '').replace(/\D/g, ''); | |||
| if (raw === '') return 0; | |||
| const parsed = parseInt(raw, 10); | |||
| if (Number.isNaN(parsed)) return 0; | |||
| if (originalQty < 1) return 0; | |||
| const minClamped = Math.max(1, parsed); | |||
| return Math.min(minClamped, originalQty); | |||
| }, [qtyToBeTransferred, originalQty]); | |||
| const remainingQty = originalQty - validatedTransferQty; | |||
| const prevAdjustmentModalOpenRef = useRef(false); | |||
| @@ -315,7 +326,7 @@ const prevAdjustmentModalOpenRef = useRef(false); | |||
| setStartLocation(lotLine.warehouse.code || ""); | |||
| setTargetLocation(null); | |||
| setTargetLocationInput(""); | |||
| setQtyToBeTransferred(lotLine.availableQty >= 1 ? 1 : 0); | |||
| setQtyToBeTransferred(""); | |||
| }, | |||
| [], | |||
| ); | |||
| @@ -471,11 +482,11 @@ const prevAdjustmentModalOpenRef = useRef(false); | |||
| setStartLocation(""); | |||
| setTargetLocation(null); | |||
| setTargetLocationInput(""); | |||
| setQtyToBeTransferred(0); | |||
| setQtyToBeTransferred(""); | |||
| }, []); | |||
| const handleSubmitStockTransfer = useCallback(async () => { | |||
| if (!selectedLotLine || !targetLocation || qtyToBeTransferred < 1) { | |||
| if (!selectedLotLine || !targetLocation || validatedTransferQty < 1 || validatedTransferQty > originalQty) { | |||
| return; | |||
| } | |||
| @@ -484,7 +495,7 @@ const prevAdjustmentModalOpenRef = useRef(false); | |||
| const request = { | |||
| inventoryLotLineId: selectedLotLine.id, | |||
| transferredQty: qtyToBeTransferred, | |||
| transferredQty: validatedTransferQty, | |||
| warehouseId: targetLocation, // targetLocation now contains warehouse ID | |||
| }; | |||
| @@ -503,7 +514,7 @@ const prevAdjustmentModalOpenRef = useRef(false); | |||
| } finally { | |||
| setIsUploading(false); | |||
| } | |||
| }, [selectedLotLine, targetLocation, qtyToBeTransferred, handleCloseStockTransferModal, setIsUploading, t, onStockTransferSuccess]); | |||
| }, [selectedLotLine, targetLocation, validatedTransferQty, originalQty, handleCloseStockTransferModal, setIsUploading, t, onStockTransferSuccess]); | |||
| return <> | |||
| <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap', mb: 2 }}> | |||
| @@ -662,15 +673,29 @@ const prevAdjustmentModalOpenRef = useRef(false); | |||
| label={t("Qty To Be Transferred")} | |||
| fullWidth | |||
| variant="outlined" | |||
| type="number" | |||
| type="text" | |||
| inputMode="numeric" | |||
| value={qtyToBeTransferred} | |||
| onChange={(e) => { | |||
| const value = parseInt(e.target.value) || 0; | |||
| const minValue = 1; | |||
| const maxValue = Math.max(0, originalQty); | |||
| setQtyToBeTransferred(Math.min(Math.max(minValue, value), maxValue)); | |||
| const raw = e.target.value.replace(/\D/g, ''); | |||
| if (raw === '') { | |||
| setQtyToBeTransferred(''); | |||
| return; | |||
| } | |||
| const parsed = parseInt(raw, 10); | |||
| if (Number.isNaN(parsed)) { | |||
| setQtyToBeTransferred(''); | |||
| return; | |||
| } | |||
| if (originalQty < 1) { | |||
| setQtyToBeTransferred(''); | |||
| return; | |||
| } | |||
| const clamped = Math.min(Math.max(1, parsed), originalQty); | |||
| setQtyToBeTransferred(String(clamped)); | |||
| }} | |||
| inputProps={{ min: 1, max: originalQty, step: 1 }} | |||
| onFocus={(e) => (e.target as HTMLInputElement).select()} | |||
| inputProps={{ pattern: "[0-9]*" }} | |||
| InputLabelProps={{ | |||
| shrink: true, | |||
| sx: { fontSize: "0.9375rem" }, | |||
| @@ -715,7 +740,7 @@ const prevAdjustmentModalOpenRef = useRef(false); | |||
| fontSize: '0.9375rem', | |||
| }} | |||
| onClick={handleSubmitStockTransfer} | |||
| disabled={!selectedLotLine || !targetLocation || qtyToBeTransferred < 1 || qtyToBeTransferred > originalQty} | |||
| disabled={!selectedLotLine || !targetLocation || validatedTransferQty < 1 || validatedTransferQty > originalQty} | |||
| > | |||
| {t("Submit")} | |||
| </Button> | |||