Files
bakery-ia/frontend/src/api/hooks/suppliers.ts

650 lines
20 KiB
TypeScript
Raw Normal View History

/**
* Suppliers React Query hooks
* Provides data fetching, caching, and state management for supplier operations
*/
import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
import { suppliersService } from '../services/suppliers';
import { ApiError } from '../client/apiClient';
import type {
SupplierCreate,
SupplierUpdate,
SupplierResponse,
SupplierSummary,
SupplierApproval,
SupplierQueryParams,
SupplierStatistics,
TopSuppliersResponse,
PurchaseOrderCreate,
PurchaseOrderUpdate,
PurchaseOrderResponse,
PurchaseOrderApproval,
PurchaseOrderQueryParams,
DeliveryCreate,
DeliveryUpdate,
DeliveryResponse,
DeliveryReceiptConfirmation,
DeliveryQueryParams,
PerformanceCalculationRequest,
PerformanceMetrics,
PerformanceAlert,
PaginatedResponse,
} from '../types/suppliers';
// Query Keys Factory
export const suppliersKeys = {
all: ['suppliers'] as const,
suppliers: {
all: () => [...suppliersKeys.all, 'suppliers'] as const,
lists: () => [...suppliersKeys.suppliers.all(), 'list'] as const,
list: (tenantId: string, params?: SupplierQueryParams) =>
[...suppliersKeys.suppliers.lists(), tenantId, params] as const,
details: () => [...suppliersKeys.suppliers.all(), 'detail'] as const,
detail: (tenantId: string, supplierId: string) =>
[...suppliersKeys.suppliers.details(), tenantId, supplierId] as const,
statistics: (tenantId: string) =>
[...suppliersKeys.suppliers.all(), 'statistics', tenantId] as const,
top: (tenantId: string) =>
[...suppliersKeys.suppliers.all(), 'top', tenantId] as const,
byType: (tenantId: string, supplierType: string) =>
[...suppliersKeys.suppliers.all(), 'by-type', tenantId, supplierType] as const,
},
purchaseOrders: {
all: () => [...suppliersKeys.all, 'purchase-orders'] as const,
lists: () => [...suppliersKeys.purchaseOrders.all(), 'list'] as const,
list: (params?: PurchaseOrderQueryParams) =>
[...suppliersKeys.purchaseOrders.lists(), params] as const,
details: () => [...suppliersKeys.purchaseOrders.all(), 'detail'] as const,
detail: (orderId: string) =>
[...suppliersKeys.purchaseOrders.details(), orderId] as const,
},
deliveries: {
all: () => [...suppliersKeys.all, 'deliveries'] as const,
lists: () => [...suppliersKeys.deliveries.all(), 'list'] as const,
list: (params?: DeliveryQueryParams) =>
[...suppliersKeys.deliveries.lists(), params] as const,
details: () => [...suppliersKeys.deliveries.all(), 'detail'] as const,
detail: (deliveryId: string) =>
[...suppliersKeys.deliveries.details(), deliveryId] as const,
},
performance: {
all: () => [...suppliersKeys.all, 'performance'] as const,
metrics: (tenantId: string, supplierId: string) =>
[...suppliersKeys.performance.all(), 'metrics', tenantId, supplierId] as const,
alerts: (tenantId: string, supplierId?: string) =>
[...suppliersKeys.performance.all(), 'alerts', tenantId, supplierId] as const,
},
} as const;
// Supplier Queries
export const useSuppliers = (
tenantId: string,
queryParams?: SupplierQueryParams,
options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
queryKey: suppliersKeys.suppliers.list(tenantId, queryParams),
queryFn: () => suppliersService.getSuppliers(tenantId, queryParams),
enabled: !!tenantId,
staleTime: 2 * 60 * 1000, // 2 minutes
...options,
});
};
export const useSupplier = (
tenantId: string,
supplierId: string,
options?: Omit<UseQueryOptions<SupplierResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<SupplierResponse, ApiError>({
queryKey: suppliersKeys.suppliers.detail(tenantId, supplierId),
queryFn: () => suppliersService.getSupplier(tenantId, supplierId),
enabled: !!tenantId && !!supplierId,
staleTime: 5 * 60 * 1000, // 5 minutes
...options,
});
};
export const useSupplierStatistics = (
tenantId: string,
options?: Omit<UseQueryOptions<SupplierStatistics, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<SupplierStatistics, ApiError>({
queryKey: suppliersKeys.suppliers.statistics(tenantId),
queryFn: () => suppliersService.getSupplierStatistics(tenantId),
enabled: !!tenantId,
staleTime: 5 * 60 * 1000, // 5 minutes
...options,
});
};
export const useActiveSuppliers = (
tenantId: string,
queryParams?: Omit<SupplierQueryParams, 'status'>,
options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
queryKey: suppliersKeys.suppliers.list(tenantId, { ...queryParams, status: 'active' }),
queryFn: () => suppliersService.getActiveSuppliers(tenantId, queryParams),
enabled: !!tenantId,
staleTime: 2 * 60 * 1000, // 2 minutes
...options,
});
};
export const useTopSuppliers = (
tenantId: string,
options?: Omit<UseQueryOptions<TopSuppliersResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<TopSuppliersResponse, ApiError>({
queryKey: suppliersKeys.suppliers.top(tenantId),
queryFn: () => suppliersService.getTopSuppliers(tenantId),
enabled: !!tenantId,
staleTime: 10 * 60 * 1000, // 10 minutes
...options,
});
};
export const usePendingApprovalSuppliers = (
tenantId: string,
options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
queryKey: suppliersKeys.suppliers.list(tenantId, { status: 'pending_approval' }),
queryFn: () => suppliersService.getPendingApprovalSuppliers(tenantId),
enabled: !!tenantId,
staleTime: 1 * 60 * 1000, // 1 minute
...options,
});
};
export const useSuppliersByType = (
tenantId: string,
supplierType: string,
queryParams?: Omit<SupplierQueryParams, 'supplier_type'>,
options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
queryKey: suppliersKeys.suppliers.byType(tenantId, supplierType),
queryFn: () => suppliersService.getSuppliersByType(tenantId, supplierType, queryParams),
enabled: !!tenantId && !!supplierType,
staleTime: 2 * 60 * 1000, // 2 minutes
...options,
});
};
// Purchase Order Queries
export const usePurchaseOrders = (
queryParams?: PurchaseOrderQueryParams,
options?: Omit<UseQueryOptions<PaginatedResponse<PurchaseOrderResponse>, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PaginatedResponse<PurchaseOrderResponse>, ApiError>({
queryKey: suppliersKeys.purchaseOrders.list(queryParams),
queryFn: () => suppliersService.getPurchaseOrders(queryParams),
staleTime: 1 * 60 * 1000, // 1 minute
...options,
});
};
export const usePurchaseOrder = (
orderId: string,
options?: Omit<UseQueryOptions<PurchaseOrderResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PurchaseOrderResponse, ApiError>({
queryKey: suppliersKeys.purchaseOrders.detail(orderId),
queryFn: () => suppliersService.getPurchaseOrder(orderId),
enabled: !!orderId,
staleTime: 2 * 60 * 1000, // 2 minutes
...options,
});
};
// Delivery Queries
export const useDeliveries = (
queryParams?: DeliveryQueryParams,
options?: Omit<UseQueryOptions<PaginatedResponse<DeliveryResponse>, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PaginatedResponse<DeliveryResponse>, ApiError>({
queryKey: suppliersKeys.deliveries.list(queryParams),
queryFn: () => suppliersService.getDeliveries(queryParams),
staleTime: 1 * 60 * 1000, // 1 minute
...options,
});
};
export const useDelivery = (
deliveryId: string,
options?: Omit<UseQueryOptions<DeliveryResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<DeliveryResponse, ApiError>({
queryKey: suppliersKeys.deliveries.detail(deliveryId),
queryFn: () => suppliersService.getDelivery(deliveryId),
enabled: !!deliveryId,
staleTime: 30 * 1000, // 30 seconds
...options,
});
};
// Performance Queries
export const useSupplierPerformanceMetrics = (
tenantId: string,
supplierId: string,
options?: Omit<UseQueryOptions<PerformanceMetrics, ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PerformanceMetrics, ApiError>({
queryKey: suppliersKeys.performance.metrics(tenantId, supplierId),
queryFn: () => suppliersService.getSupplierPerformanceMetrics(tenantId, supplierId),
enabled: !!tenantId && !!supplierId,
staleTime: 10 * 60 * 1000, // 10 minutes
...options,
});
};
export const usePerformanceAlerts = (
tenantId: string,
supplierId?: string,
options?: Omit<UseQueryOptions<PerformanceAlert[], ApiError>, 'queryKey' | 'queryFn'>
) => {
return useQuery<PerformanceAlert[], ApiError>({
queryKey: suppliersKeys.performance.alerts(tenantId, supplierId),
queryFn: () => suppliersService.getPerformanceAlerts(tenantId, supplierId),
enabled: !!tenantId,
staleTime: 2 * 60 * 1000, // 2 minutes
...options,
});
};
// Supplier Mutations
export const useCreateSupplier = (
options?: UseMutationOptions<
SupplierResponse,
ApiError,
{ tenantId: string; supplierData: SupplierCreate }
>
) => {
const queryClient = useQueryClient();
return useMutation<
SupplierResponse,
ApiError,
{ tenantId: string; supplierData: SupplierCreate }
>({
mutationFn: ({ tenantId, supplierData }) =>
suppliersService.createSupplier(tenantId, supplierData),
onSuccess: (data, { tenantId }) => {
// Add to cache
queryClient.setQueryData(
suppliersKeys.suppliers.detail(tenantId, data.id),
data
);
// Invalidate lists and statistics
queryClient.invalidateQueries({
queryKey: suppliersKeys.suppliers.lists()
});
queryClient.invalidateQueries({
queryKey: suppliersKeys.suppliers.statistics(tenantId)
});
},
...options,
});
};
export const useUpdateSupplier = (
options?: UseMutationOptions<
SupplierResponse,
ApiError,
{ tenantId: string; supplierId: string; updateData: SupplierUpdate }
>
) => {
const queryClient = useQueryClient();
return useMutation<
SupplierResponse,
ApiError,
{ tenantId: string; supplierId: string; updateData: SupplierUpdate }
>({
mutationFn: ({ tenantId, supplierId, updateData }) =>
suppliersService.updateSupplier(tenantId, supplierId, updateData),
onSuccess: (data, { tenantId, supplierId }) => {
// Update cache
queryClient.setQueryData(
suppliersKeys.suppliers.detail(tenantId, supplierId),
data
);
// Invalidate lists
queryClient.invalidateQueries({
queryKey: suppliersKeys.suppliers.lists()
});
},
...options,
});
};
export const useDeleteSupplier = (
options?: UseMutationOptions<
{ message: string },
ApiError,
{ tenantId: string; supplierId: string }
>
) => {
const queryClient = useQueryClient();
return useMutation<
{ message: string },
ApiError,
{ tenantId: string; supplierId: string }
>({
mutationFn: ({ tenantId, supplierId }) =>
suppliersService.deleteSupplier(tenantId, supplierId),
onSuccess: (_, { tenantId, supplierId }) => {
// Remove from cache
queryClient.removeQueries({
queryKey: suppliersKeys.suppliers.detail(tenantId, supplierId)
});
// Invalidate lists and statistics
queryClient.invalidateQueries({
queryKey: suppliersKeys.suppliers.lists()
});
queryClient.invalidateQueries({
queryKey: suppliersKeys.suppliers.statistics(tenantId)
});
},
...options,
});
};
export const useApproveSupplier = (
options?: UseMutationOptions<
SupplierResponse,
ApiError,
{ tenantId: string; supplierId: string; approval: SupplierApproval }
>
) => {
const queryClient = useQueryClient();
return useMutation<
SupplierResponse,
ApiError,
{ tenantId: string; supplierId: string; approval: SupplierApproval }
>({
mutationFn: ({ tenantId, supplierId, approval }) =>
suppliersService.approveSupplier(tenantId, supplierId, approval),
onSuccess: (data, { tenantId, supplierId }) => {
// Update cache
queryClient.setQueryData(
suppliersKeys.suppliers.detail(tenantId, supplierId),
data
);
// Invalidate lists and statistics
queryClient.invalidateQueries({
queryKey: suppliersKeys.suppliers.lists()
});
queryClient.invalidateQueries({
queryKey: suppliersKeys.suppliers.statistics(tenantId)
});
},
...options,
});
};
// Purchase Order Mutations
export const useCreatePurchaseOrder = (
options?: UseMutationOptions<PurchaseOrderResponse, ApiError, PurchaseOrderCreate>
) => {
const queryClient = useQueryClient();
return useMutation<PurchaseOrderResponse, ApiError, PurchaseOrderCreate>({
mutationFn: (orderData) => suppliersService.createPurchaseOrder(orderData),
onSuccess: (data) => {
// Add to cache
queryClient.setQueryData(
suppliersKeys.purchaseOrders.detail(data.id),
data
);
// Invalidate lists
queryClient.invalidateQueries({
queryKey: suppliersKeys.purchaseOrders.lists()
});
},
...options,
});
};
export const useUpdatePurchaseOrder = (
options?: UseMutationOptions<
PurchaseOrderResponse,
ApiError,
{ orderId: string; updateData: PurchaseOrderUpdate }
>
) => {
const queryClient = useQueryClient();
return useMutation<
PurchaseOrderResponse,
ApiError,
{ orderId: string; updateData: PurchaseOrderUpdate }
>({
mutationFn: ({ orderId, updateData }) =>
suppliersService.updatePurchaseOrder(orderId, updateData),
onSuccess: (data, { orderId }) => {
// Update cache
queryClient.setQueryData(
suppliersKeys.purchaseOrders.detail(orderId),
data
);
// Invalidate lists
queryClient.invalidateQueries({
queryKey: suppliersKeys.purchaseOrders.lists()
});
},
...options,
});
};
export const useApprovePurchaseOrder = (
options?: UseMutationOptions<
PurchaseOrderResponse,
ApiError,
{ orderId: string; approval: PurchaseOrderApproval }
>
) => {
const queryClient = useQueryClient();
return useMutation<
PurchaseOrderResponse,
ApiError,
{ orderId: string; approval: PurchaseOrderApproval }
>({
mutationFn: ({ orderId, approval }) =>
suppliersService.approvePurchaseOrder(orderId, approval),
onSuccess: (data, { orderId }) => {
// Update cache
queryClient.setQueryData(
suppliersKeys.purchaseOrders.detail(orderId),
data
);
// Invalidate lists
queryClient.invalidateQueries({
queryKey: suppliersKeys.purchaseOrders.lists()
});
},
...options,
});
};
// Delivery Mutations
export const useCreateDelivery = (
options?: UseMutationOptions<DeliveryResponse, ApiError, DeliveryCreate>
) => {
const queryClient = useQueryClient();
return useMutation<DeliveryResponse, ApiError, DeliveryCreate>({
mutationFn: (deliveryData) => suppliersService.createDelivery(deliveryData),
onSuccess: (data) => {
// Add to cache
queryClient.setQueryData(
suppliersKeys.deliveries.detail(data.id),
data
);
// Invalidate lists
queryClient.invalidateQueries({
queryKey: suppliersKeys.deliveries.lists()
});
},
...options,
});
};
export const useUpdateDelivery = (
options?: UseMutationOptions<
DeliveryResponse,
ApiError,
{ deliveryId: string; updateData: DeliveryUpdate }
>
) => {
const queryClient = useQueryClient();
return useMutation<
DeliveryResponse,
ApiError,
{ deliveryId: string; updateData: DeliveryUpdate }
>({
mutationFn: ({ deliveryId, updateData }) =>
suppliersService.updateDelivery(deliveryId, updateData),
onSuccess: (data, { deliveryId }) => {
// Update cache
queryClient.setQueryData(
suppliersKeys.deliveries.detail(deliveryId),
data
);
// Invalidate lists
queryClient.invalidateQueries({
queryKey: suppliersKeys.deliveries.lists()
});
},
...options,
});
};
export const useConfirmDeliveryReceipt = (
options?: UseMutationOptions<
DeliveryResponse,
ApiError,
{ deliveryId: string; confirmation: DeliveryReceiptConfirmation }
>
) => {
const queryClient = useQueryClient();
return useMutation<
DeliveryResponse,
ApiError,
{ deliveryId: string; confirmation: DeliveryReceiptConfirmation }
>({
mutationFn: ({ deliveryId, confirmation }) =>
suppliersService.confirmDeliveryReceipt(deliveryId, confirmation),
onSuccess: (data, { deliveryId }) => {
// Update cache
queryClient.setQueryData(
suppliersKeys.deliveries.detail(deliveryId),
data
);
// Invalidate lists and performance metrics
queryClient.invalidateQueries({
queryKey: suppliersKeys.deliveries.lists()
});
queryClient.invalidateQueries({
queryKey: suppliersKeys.performance.all()
});
},
...options,
});
};
// Performance Mutations
export const useCalculateSupplierPerformance = (
options?: UseMutationOptions<
{ message: string; calculation_id: string },
ApiError,
{ tenantId: string; supplierId: string; request?: PerformanceCalculationRequest }
>
) => {
const queryClient = useQueryClient();
return useMutation<
{ message: string; calculation_id: string },
ApiError,
{ tenantId: string; supplierId: string; request?: PerformanceCalculationRequest }
>({
mutationFn: ({ tenantId, supplierId, request }) =>
suppliersService.calculateSupplierPerformance(tenantId, supplierId, request),
onSuccess: (_, { tenantId, supplierId }) => {
// Invalidate performance metrics after calculation
queryClient.invalidateQueries({
queryKey: suppliersKeys.performance.metrics(tenantId, supplierId)
});
queryClient.invalidateQueries({
queryKey: suppliersKeys.performance.alerts(tenantId)
});
},
...options,
});
};
export const useEvaluatePerformanceAlerts = (
options?: UseMutationOptions<
{ alerts_generated: number; message: string },
ApiError,
{ tenantId: string }
>
) => {
const queryClient = useQueryClient();
return useMutation<
{ alerts_generated: number; message: string },
ApiError,
{ tenantId: string }
>({
mutationFn: ({ tenantId }) => suppliersService.evaluatePerformanceAlerts(tenantId),
onSuccess: (_, { tenantId }) => {
// Invalidate performance alerts
queryClient.invalidateQueries({
queryKey: suppliersKeys.performance.alerts(tenantId)
});
},
...options,
});
};
// Utility Hooks
export const useSuppliersByStatus = (tenantId: string, status: string) => {
return useSuppliers(tenantId, { status: status as any });
};
export const useSuppliersCount = (tenantId: string) => {
const { data: statistics } = useSupplierStatistics(tenantId);
return statistics?.total_suppliers || 0;
};
export const useActiveSuppliersCount = (tenantId: string) => {
const { data: statistics } = useSupplierStatistics(tenantId);
return statistics?.active_suppliers || 0;
};
export const usePendingOrdersCount = (supplierId?: string) => {
const { data: orders } = usePurchaseOrders({
supplier_id: supplierId,
status: 'pending_approval',
limit: 1000
});
return orders?.data?.length || 0;
};