114 lines
3.4 KiB
TypeScript
114 lines
3.4 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react';
|
|
import { inventoryService } from '../mock';
|
|
import { Warehouse } from '../../entities/inventory/warehouse';
|
|
import { StockItem, StockMovement, GoodsReceipt } from '../contracts/inventory';
|
|
import { useStorageListener } from './useStorageListener';
|
|
|
|
export function useInventory() {
|
|
const [warehouses, setWarehouses] = useState<Warehouse[]>([]);
|
|
const [stockItems, setStockItems] = useState<StockItem[]>([]);
|
|
const [movements, setMovements] = useState<StockMovement[]>([]);
|
|
const [receipts, setReceipts] = useState<GoodsReceipt[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<Error | null>(null);
|
|
|
|
const fetchAll = useCallback(async () => {
|
|
try {
|
|
setLoading(true);
|
|
setError(null);
|
|
const [whRes, stkRes, movRes, recRes] = await Promise.all([
|
|
inventoryService.warehouses.list({ pageSize: 50 }),
|
|
inventoryService.stockItems.list({ pageSize: 200 }),
|
|
inventoryService.movements.list({ pageSize: 100 }),
|
|
inventoryService.receipts.list({ pageSize: 100 }),
|
|
]);
|
|
setWarehouses(whRes.items);
|
|
setStockItems(stkRes.items);
|
|
setMovements(movRes.items);
|
|
setReceipts(recRes.items);
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
let active = true;
|
|
void Promise.resolve().then(() => {
|
|
if (active) fetchAll();
|
|
});
|
|
return () => {
|
|
active = false;
|
|
};
|
|
}, [fetchAll]);
|
|
|
|
useStorageListener('records:changed', (payload) => {
|
|
if (
|
|
payload.entityType === 'warehouse' ||
|
|
payload.entityType === 'stock_item' ||
|
|
payload.entityType === 'stock_movement' ||
|
|
payload.entityType === 'goods_receipt' ||
|
|
payload.entityType === 'stock_reservation'
|
|
) {
|
|
fetchAll();
|
|
}
|
|
});
|
|
|
|
useStorageListener('storage:reset', fetchAll);
|
|
useStorageListener('snapshot:imported', fetchAll);
|
|
|
|
const adjustStock = useCallback(
|
|
async (warehouseId: string, productId: string, delta: number, reason: string) => {
|
|
return inventoryService.adjustStock(warehouseId, productId, delta, reason);
|
|
},
|
|
[]
|
|
);
|
|
|
|
const reserveStock = useCallback(
|
|
async (orderId: string, warehouseId: string, productId: string, quantity: number) => {
|
|
return inventoryService.reserveStock(orderId, warehouseId, productId, quantity);
|
|
},
|
|
[]
|
|
);
|
|
|
|
const cancelOrderReservations = useCallback(async (orderId: string) => {
|
|
return inventoryService.cancelOrderReservations(orderId);
|
|
}, []);
|
|
|
|
const receiveGoods = useCallback(async (receiptId: string): Promise<GoodsReceipt> => {
|
|
return inventoryService.receiveGoods(receiptId);
|
|
}, []);
|
|
|
|
const createAndReceiveGoods = useCallback(
|
|
async (
|
|
warehouseId: string,
|
|
receiptNumber: string,
|
|
supplierName: string,
|
|
items: import('../contracts/inventory').GoodsReceiptItem[]
|
|
): Promise<GoodsReceipt> => {
|
|
return inventoryService.createAndReceiveGoods(
|
|
warehouseId,
|
|
receiptNumber,
|
|
supplierName,
|
|
items
|
|
);
|
|
},
|
|
[]
|
|
);
|
|
|
|
return {
|
|
warehouses,
|
|
stockItems,
|
|
movements,
|
|
receipts,
|
|
loading,
|
|
error,
|
|
refetch: fetchAll,
|
|
adjustStock,
|
|
reserveStock,
|
|
cancelOrderReservations,
|
|
receiveGoods,
|
|
createAndReceiveGoods,
|
|
};
|
|
}
|