fix: cache product stock

This commit is contained in:
ValdiANS
2026-05-22 10:17:04 +07:00
parent 9a56bf732a
commit 07dd2d26be
@@ -56,6 +56,9 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
const [productQtyErrorShown, setProductQtyErrorShown] = useState(false); const [productQtyErrorShown, setProductQtyErrorShown] = useState(false);
const [deliveryQtyErrorShown, setDeliveryQtyErrorShown] = useState(false); const [deliveryQtyErrorShown, setDeliveryQtyErrorShown] = useState(false);
const [isInitialized, setIsInitialized] = useState(false); const [isInitialized, setIsInitialized] = useState(false);
const productStockCacheRef = useRef<
Map<number, { quantity: number; transfer_available_qty?: number }>
>(new Map());
// ===== FORM HANDLERS ===== // ===== FORM HANDLERS =====
const createMovementHandler = useCallback( const createMovementHandler = useCallback(
@@ -337,6 +340,7 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
prevSourceWarehouseId !== currentSourceWarehouseId && prevSourceWarehouseId !== currentSourceWarehouseId &&
prevSourceWarehouseId !== null prevSourceWarehouseId !== null
) { ) {
productStockCacheRef.current = new Map();
formik.setFieldValue('products', [ formik.setFieldValue('products', [
{ {
product: null, product: null,
@@ -399,6 +403,15 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
: []; : [];
}, [productWarehouses]); }, [productWarehouses]);
useEffect(() => {
productWarehouseOptions.forEach((pw) => {
productStockCacheRef.current.set(pw.product_id, {
quantity: pw.quantity,
transfer_available_qty: pw.transfer_available_qty,
});
});
}, [productWarehouseOptions]);
// ===== HELPER FUNCTIONS ===== // ===== HELPER FUNCTIONS =====
const isRepeaterInputError = <T extends 'products' | 'deliveries'>( const isRepeaterInputError = <T extends 'products' | 'deliveries'>(
arrayName: T, arrayName: T,
@@ -840,15 +853,12 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
const getAvailableStock = useCallback( const getAvailableStock = useCallback(
(productId: number) => { (productId: number) => {
if (type === 'detail') return 0; if (type === 'detail') return 0;
const productWarehouse = productWarehouseOptions.find( const live = productWarehouseOptions.find(
(pw) => pw.product_id === productId (pw) => pw.product_id === productId
); );
if (live) return live.transfer_available_qty ?? live.quantity ?? 0;
return ( const cached = productStockCacheRef.current.get(productId);
productWarehouse?.transfer_available_qty ?? return cached?.transfer_available_qty ?? cached?.quantity ?? 0;
productWarehouse?.quantity ??
0
);
}, },
[productWarehouseOptions, type] [productWarehouseOptions, type]
); );
@@ -856,20 +866,25 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
const getTotalStock = useCallback( const getTotalStock = useCallback(
(productId: number) => { (productId: number) => {
if (type === 'detail') return 0; if (type === 'detail') return 0;
const productWarehouse = productWarehouseOptions.find( const live = productWarehouseOptions.find(
(pw) => pw.product_id === productId (pw) => pw.product_id === productId
); );
return productWarehouse?.quantity ?? 0; if (live) return live.quantity ?? 0;
return productStockCacheRef.current.get(productId)?.quantity ?? 0;
}, },
[productWarehouseOptions, type] [productWarehouseOptions, type]
); );
const hasAvailableQty = useCallback( const hasAvailableQty = useCallback(
(productId: number) => { (productId: number) => {
const productWarehouse = productWarehouseOptions.find( const live = productWarehouseOptions.find(
(pw) => pw.product_id === productId (pw) => pw.product_id === productId
); );
return productWarehouse?.transfer_available_qty !== undefined; if (live) return live.transfer_available_qty !== undefined;
return (
productStockCacheRef.current.get(productId)?.transfer_available_qty !==
undefined
);
}, },
[productWarehouseOptions] [productWarehouseOptions]
); );