krona-front/src/services/hooks/useInventory.ts

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,
};
}