This commit is contained in:
Urtzi Alfaro
2026-01-01 19:01:33 +01:00
parent d6728b4bd8
commit 93c9475239
10 changed files with 286 additions and 84 deletions

View File

@@ -23,6 +23,7 @@ import {
ProductTransformationResponse,
ProductionStage,
DeletionSummary,
BulkStockResponse,
} from '../types/inventory';
import { ApiError } from '../client';
@@ -342,7 +343,7 @@ export const useAddStock = (
options?: UseMutationOptions<StockResponse, ApiError, { tenantId: string; stockData: StockCreate }>
) => {
const queryClient = useQueryClient();
return useMutation<StockResponse, ApiError, { tenantId: string; stockData: StockCreate }>({
mutationFn: ({ tenantId, stockData }) => inventoryService.addStock(tenantId, stockData),
onSuccess: (data, { tenantId }) => {
@@ -355,6 +356,30 @@ export const useAddStock = (
});
};
export const useBulkAddStock = (
options?: UseMutationOptions<BulkStockResponse, ApiError, { tenantId: string; stocks: StockCreate[] }>
) => {
const queryClient = useQueryClient();
return useMutation<BulkStockResponse, ApiError, { tenantId: string; stocks: StockCreate[] }>({
mutationFn: ({ tenantId, stocks }) => inventoryService.bulkAddStock(tenantId, stocks),
onSuccess: (data, { tenantId }) => {
// Invalidate all stock queries since multiple ingredients may have been affected
queryClient.invalidateQueries({ queryKey: inventoryKeys.stock.lists() });
queryClient.invalidateQueries({ queryKey: inventoryKeys.ingredients.lists() });
// Invalidate per-ingredient stock queries
data.results.forEach((result) => {
if (result.success && result.stock) {
queryClient.invalidateQueries({
queryKey: inventoryKeys.stock.byIngredient(tenantId, result.stock.ingredient_id)
});
}
});
},
...options,
});
};
export const useUpdateStock = (
options?: UseMutationOptions<
StockResponse,

View File

@@ -29,6 +29,7 @@ import {
StockFilter,
StockMovementCreate,
StockMovementResponse,
BulkStockResponse,
// Operations
StockConsumptionRequest,
StockConsumptionResponse,
@@ -162,6 +163,16 @@ export class InventoryService {
);
}
async bulkAddStock(
tenantId: string,
stocks: StockCreate[]
): Promise<BulkStockResponse> {
return apiClient.post<BulkStockResponse>(
`${this.baseUrl}/${tenantId}/inventory/stock/bulk`,
{ stocks }
);
}
async getStock(tenantId: string, stockId: string): Promise<StockResponse> {
return apiClient.get<StockResponse>(
`${this.baseUrl}/${tenantId}/inventory/stock/${stockId}`

View File

@@ -330,6 +330,28 @@ export interface StockResponse {
ingredient?: IngredientResponse | null;
}
// ===== BULK STOCK SCHEMAS =====
// Mirror: BulkStockCreate, BulkStockResult, BulkStockResponse from inventory.py
export interface BulkStockCreate {
stocks: StockCreate[];
}
export interface BulkStockResult {
index: number;
success: boolean;
stock: StockResponse | null;
error: string | null;
}
export interface BulkStockResponse {
total_requested: number;
total_created: number;
total_failed: number;
results: BulkStockResult[];
transaction_id: string;
}
// ===== STOCK MOVEMENT SCHEMAS =====
// Mirror: StockMovementCreate from inventory.py:277