1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 15:49:35 +01:00
effigenix/frontend/apps/cli/src/hooks/useStocks.ts
Sebastian Frick 376557925a feat(tui): TUI für Produktionsauftrag-Freigabe, Bestandsreservierung und Reservierungs-Freigabe
- ProductionOrderCreateScreen: Nach Anlage Freigabe per [F] mit Statusanzeige
- StockDetailScreen: Reservierungen-Tabelle, Menü für Reservieren/Freigeben
- ReserveStockScreen: Neues Formular (Referenztyp, Referenz-ID, Menge, Einheit, Priorität)
- API-Client: release(), reserveStock(), releaseReservation() Methoden
- Hooks: releaseProductionOrder(), reserveStock(), releaseReservation()
- Types: ReservationDTO, StockBatchAllocationDTO, ReserveStockRequest exportiert
- DB: Migration 027 erweitert chk_production_order_status um RELEASED
2026-02-24 00:57:40 +01:00

171 lines
5.6 KiB
TypeScript

import { useState, useCallback } from 'react';
import type {
StockDTO,
StockBatchDTO,
AddStockBatchRequest,
CreateStockRequest,
UpdateStockRequest,
StockFilter,
ReserveStockRequest,
} from '@effigenix/api-client';
import { client } from '../utils/api-client.js';
interface StocksState {
stocks: StockDTO[];
stock: StockDTO | null;
loading: boolean;
error: string | null;
}
function errorMessage(err: unknown): string {
return err instanceof Error ? err.message : 'Unbekannter Fehler';
}
export function useStocks() {
const [state, setState] = useState<StocksState>({
stocks: [],
stock: null,
loading: false,
error: null,
});
const fetchStocks = useCallback(async (filter?: StockFilter) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
const stocks = await client.stocks.list(filter);
setState((s) => ({ ...s, stocks, loading: false, error: null }));
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
}
}, []);
const fetchStock = useCallback(async (id: string) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
const stock = await client.stocks.getById(id);
setState((s) => ({ ...s, stock, loading: false, error: null }));
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
}
}, []);
const createStock = useCallback(async (request: CreateStockRequest) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
const result = await client.stocks.create(request);
setState((s) => ({ ...s, loading: false, error: null }));
return result;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return null;
}
}, []);
const updateStock = useCallback(async (id: string, request: UpdateStockRequest) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
const stock = await client.stocks.update(id, request);
setState((s) => ({ ...s, stock, loading: false, error: null }));
return stock;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return null;
}
}, []);
const addBatch = useCallback(async (stockId: string, request: AddStockBatchRequest): Promise<StockBatchDTO | null> => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
const batch = await client.stocks.addBatch(stockId, request);
setState((s) => ({ ...s, loading: false, error: null }));
return batch;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return null;
}
}, []);
const removeBatch = useCallback(async (stockId: string, batchId: string, quantityAmount: string, quantityUnit: string) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
await client.stocks.removeBatch(stockId, batchId, { quantityAmount, quantityUnit });
const stock = await client.stocks.getById(stockId);
setState((s) => ({ ...s, stock, loading: false, error: null }));
return true;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return false;
}
}, []);
const blockBatch = useCallback(async (stockId: string, batchId: string, reason: string) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
await client.stocks.blockBatch(stockId, batchId, { reason });
const stock = await client.stocks.getById(stockId);
setState((s) => ({ ...s, stock, loading: false, error: null }));
return true;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return false;
}
}, []);
const unblockBatch = useCallback(async (stockId: string, batchId: string) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
await client.stocks.unblockBatch(stockId, batchId);
const stock = await client.stocks.getById(stockId);
setState((s) => ({ ...s, stock, loading: false, error: null }));
return true;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return false;
}
}, []);
const reserveStock = useCallback(async (stockId: string, request: ReserveStockRequest) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
const reservation = await client.stocks.reserveStock(stockId, request);
const stock = await client.stocks.getById(stockId);
setState((s) => ({ ...s, stock, loading: false, error: null }));
return reservation;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return null;
}
}, []);
const releaseReservation = useCallback(async (stockId: string, reservationId: string) => {
setState((s) => ({ ...s, loading: true, error: null }));
try {
await client.stocks.releaseReservation(stockId, reservationId);
const stock = await client.stocks.getById(stockId);
setState((s) => ({ ...s, stock, loading: false, error: null }));
return true;
} catch (err) {
setState((s) => ({ ...s, loading: false, error: errorMessage(err) }));
return false;
}
}, []);
const clearError = useCallback(() => {
setState((s) => ({ ...s, error: null }));
}, []);
return {
...state,
fetchStocks,
fetchStock,
createStock,
updateStock,
addBatch,
removeBatch,
blockBatch,
unblockBatch,
reserveStock,
releaseReservation,
clearError,
};
}