Add frontend procurement implementation
This commit is contained in:
@@ -18,6 +18,19 @@ import {
|
||||
GetCustomersParams,
|
||||
UpdateOrderStatusParams,
|
||||
GetDemandRequirementsParams,
|
||||
// Procurement types
|
||||
ProcurementPlanResponse,
|
||||
ProcurementPlanCreate,
|
||||
ProcurementPlanUpdate,
|
||||
ProcurementRequirementResponse,
|
||||
ProcurementRequirementUpdate,
|
||||
ProcurementDashboardData,
|
||||
GeneratePlanRequest,
|
||||
GeneratePlanResponse,
|
||||
PaginatedProcurementPlans,
|
||||
GetProcurementPlansParams,
|
||||
GetPlanRequirementsParams,
|
||||
UpdatePlanStatusParams,
|
||||
} from '../types/orders';
|
||||
import { ApiError } from '../client/apiClient';
|
||||
|
||||
@@ -42,6 +55,17 @@ export const ordersKeys = {
|
||||
|
||||
// Status
|
||||
status: (tenantId: string) => [...ordersKeys.all, 'status', tenantId] as const,
|
||||
|
||||
// Procurement
|
||||
procurement: () => [...ordersKeys.all, 'procurement'] as const,
|
||||
procurementPlans: (params: GetProcurementPlansParams) => [...ordersKeys.procurement(), 'plans', params] as const,
|
||||
procurementPlan: (tenantId: string, planId: string) => [...ordersKeys.procurement(), 'plan', tenantId, planId] as const,
|
||||
procurementPlanByDate: (tenantId: string, date: string) => [...ordersKeys.procurement(), 'plan-by-date', tenantId, date] as const,
|
||||
currentProcurementPlan: (tenantId: string) => [...ordersKeys.procurement(), 'current-plan', tenantId] as const,
|
||||
procurementDashboard: (tenantId: string) => [...ordersKeys.procurement(), 'dashboard', tenantId] as const,
|
||||
planRequirements: (params: GetPlanRequirementsParams) => [...ordersKeys.procurement(), 'requirements', params] as const,
|
||||
criticalRequirements: (tenantId: string) => [...ordersKeys.procurement(), 'critical-requirements', tenantId] as const,
|
||||
procurementHealth: (tenantId: string) => [...ordersKeys.procurement(), 'health', tenantId] as const,
|
||||
} as const;
|
||||
|
||||
// ===== Order Queries =====
|
||||
@@ -329,4 +353,195 @@ export const useInvalidateOrders = () => {
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ===== Procurement Queries =====
|
||||
|
||||
export const useProcurementPlans = (
|
||||
params: GetProcurementPlansParams,
|
||||
options?: Omit<UseQueryOptions<PaginatedProcurementPlans, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<PaginatedProcurementPlans, ApiError>({
|
||||
queryKey: ordersKeys.procurementPlans(params),
|
||||
queryFn: () => OrdersService.getProcurementPlans(params),
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
enabled: !!params.tenant_id,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useProcurementPlan = (
|
||||
tenantId: string,
|
||||
planId: string,
|
||||
options?: Omit<UseQueryOptions<ProcurementPlanResponse | null, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<ProcurementPlanResponse | null, ApiError>({
|
||||
queryKey: ordersKeys.procurementPlan(tenantId, planId),
|
||||
queryFn: () => OrdersService.getProcurementPlanById(tenantId, planId),
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
enabled: !!tenantId && !!planId,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useProcurementPlanByDate = (
|
||||
tenantId: string,
|
||||
planDate: string,
|
||||
options?: Omit<UseQueryOptions<ProcurementPlanResponse | null, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<ProcurementPlanResponse | null, ApiError>({
|
||||
queryKey: ordersKeys.procurementPlanByDate(tenantId, planDate),
|
||||
queryFn: () => OrdersService.getProcurementPlanByDate(tenantId, planDate),
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
enabled: !!tenantId && !!planDate,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useCurrentProcurementPlan = (
|
||||
tenantId: string,
|
||||
options?: Omit<UseQueryOptions<ProcurementPlanResponse | null, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<ProcurementPlanResponse | null, ApiError>({
|
||||
queryKey: ordersKeys.currentProcurementPlan(tenantId),
|
||||
queryFn: () => OrdersService.getCurrentProcurementPlan(tenantId),
|
||||
staleTime: 1 * 60 * 1000, // 1 minute
|
||||
enabled: !!tenantId,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useProcurementDashboard = (
|
||||
tenantId: string,
|
||||
options?: Omit<UseQueryOptions<ProcurementDashboardData | null, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<ProcurementDashboardData | null, ApiError>({
|
||||
queryKey: ordersKeys.procurementDashboard(tenantId),
|
||||
queryFn: () => OrdersService.getProcurementDashboard(tenantId),
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
enabled: !!tenantId,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const usePlanRequirements = (
|
||||
params: GetPlanRequirementsParams,
|
||||
options?: Omit<UseQueryOptions<ProcurementRequirementResponse[], ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<ProcurementRequirementResponse[], ApiError>({
|
||||
queryKey: ordersKeys.planRequirements(params),
|
||||
queryFn: () => OrdersService.getPlanRequirements(params),
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
enabled: !!params.tenant_id && !!params.plan_id,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useCriticalRequirements = (
|
||||
tenantId: string,
|
||||
options?: Omit<UseQueryOptions<ProcurementRequirementResponse[], ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<ProcurementRequirementResponse[], ApiError>({
|
||||
queryKey: ordersKeys.criticalRequirements(tenantId),
|
||||
queryFn: () => OrdersService.getCriticalRequirements(tenantId),
|
||||
staleTime: 1 * 60 * 1000, // 1 minute
|
||||
enabled: !!tenantId,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useProcurementHealth = (
|
||||
tenantId: string,
|
||||
options?: Omit<UseQueryOptions<{ status: string; service: string; procurement_enabled: boolean; timestamp: string }, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<{ status: string; service: string; procurement_enabled: boolean; timestamp: string }, ApiError>({
|
||||
queryKey: ordersKeys.procurementHealth(tenantId),
|
||||
queryFn: () => OrdersService.getProcurementHealth(tenantId),
|
||||
staleTime: 30 * 1000, // 30 seconds
|
||||
enabled: !!tenantId,
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
// ===== Procurement Mutations =====
|
||||
|
||||
export const useGenerateProcurementPlan = (
|
||||
options?: UseMutationOptions<GeneratePlanResponse, ApiError, { tenantId: string; request: GeneratePlanRequest }>
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<GeneratePlanResponse, ApiError, { tenantId: string; request: GeneratePlanRequest }>({
|
||||
mutationFn: ({ tenantId, request }) => OrdersService.generateProcurementPlan(tenantId, request),
|
||||
onSuccess: (data, variables) => {
|
||||
// Invalidate all procurement queries for this tenant
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ordersKeys.procurement(),
|
||||
predicate: (query) => {
|
||||
return JSON.stringify(query.queryKey).includes(variables.tenantId);
|
||||
},
|
||||
});
|
||||
|
||||
// If plan was generated successfully, cache it
|
||||
if (data.success && data.plan) {
|
||||
queryClient.setQueryData(
|
||||
ordersKeys.procurementPlan(variables.tenantId, data.plan.id),
|
||||
data.plan
|
||||
);
|
||||
}
|
||||
},
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateProcurementPlanStatus = (
|
||||
options?: UseMutationOptions<ProcurementPlanResponse, ApiError, UpdatePlanStatusParams>
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<ProcurementPlanResponse, ApiError, UpdatePlanStatusParams>({
|
||||
mutationFn: (params) => OrdersService.updateProcurementPlanStatus(params),
|
||||
onSuccess: (data, variables) => {
|
||||
// Update the specific plan in cache
|
||||
queryClient.setQueryData(
|
||||
ordersKeys.procurementPlan(variables.tenant_id, variables.plan_id),
|
||||
data
|
||||
);
|
||||
|
||||
// Invalidate plans list
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ordersKeys.procurement(),
|
||||
predicate: (query) => {
|
||||
const queryKey = query.queryKey as string[];
|
||||
return queryKey.includes('plans') &&
|
||||
JSON.stringify(queryKey).includes(variables.tenant_id);
|
||||
},
|
||||
});
|
||||
|
||||
// Invalidate dashboard
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ordersKeys.procurementDashboard(variables.tenant_id),
|
||||
});
|
||||
},
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
export const useTriggerDailyScheduler = (
|
||||
options?: UseMutationOptions<{ success: boolean; message: string; tenant_id: string }, ApiError, string>
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<{ success: boolean; message: string; tenant_id: string }, ApiError, string>({
|
||||
mutationFn: (tenantId) => OrdersService.triggerDailyScheduler(tenantId),
|
||||
onSuccess: (data, tenantId) => {
|
||||
// Invalidate all procurement data for this tenant
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ordersKeys.procurement(),
|
||||
predicate: (query) => {
|
||||
return JSON.stringify(query.queryKey).includes(tenantId);
|
||||
},
|
||||
});
|
||||
},
|
||||
...options,
|
||||
});
|
||||
};
|
||||
@@ -269,6 +269,30 @@ export type {
|
||||
GetCustomersParams,
|
||||
UpdateOrderStatusParams,
|
||||
GetDemandRequirementsParams,
|
||||
// Procurement types
|
||||
ProcurementPlanType,
|
||||
ProcurementStrategy,
|
||||
RiskLevel,
|
||||
RequirementStatus,
|
||||
PlanStatus,
|
||||
DeliveryStatus,
|
||||
ProcurementRequirementBase,
|
||||
ProcurementRequirementCreate,
|
||||
ProcurementRequirementUpdate,
|
||||
ProcurementRequirementResponse,
|
||||
ProcurementPlanBase,
|
||||
ProcurementPlanCreate,
|
||||
ProcurementPlanUpdate,
|
||||
ProcurementPlanResponse,
|
||||
ProcurementSummary,
|
||||
ProcurementDashboardData,
|
||||
GeneratePlanRequest,
|
||||
GeneratePlanResponse,
|
||||
PaginatedProcurementPlans,
|
||||
ForecastRequest,
|
||||
GetProcurementPlansParams,
|
||||
GetPlanRequirementsParams,
|
||||
UpdatePlanStatusParams,
|
||||
} from './types/orders';
|
||||
|
||||
// Hooks - Auth
|
||||
@@ -512,6 +536,18 @@ export {
|
||||
useCreateCustomer,
|
||||
useUpdateCustomer,
|
||||
useInvalidateOrders,
|
||||
// Procurement hooks
|
||||
useProcurementPlans,
|
||||
useProcurementPlan,
|
||||
useProcurementPlanByDate,
|
||||
useCurrentProcurementPlan,
|
||||
useProcurementDashboard,
|
||||
usePlanRequirements,
|
||||
useCriticalRequirements,
|
||||
useProcurementHealth,
|
||||
useGenerateProcurementPlan,
|
||||
useUpdateProcurementPlanStatus,
|
||||
useTriggerDailyScheduler,
|
||||
ordersKeys,
|
||||
} from './hooks/orders';
|
||||
|
||||
|
||||
@@ -21,6 +21,19 @@ import {
|
||||
GetCustomersParams,
|
||||
UpdateOrderStatusParams,
|
||||
GetDemandRequirementsParams,
|
||||
// Procurement types
|
||||
ProcurementPlanResponse,
|
||||
ProcurementPlanCreate,
|
||||
ProcurementPlanUpdate,
|
||||
ProcurementRequirementResponse,
|
||||
ProcurementRequirementUpdate,
|
||||
ProcurementDashboardData,
|
||||
GeneratePlanRequest,
|
||||
GeneratePlanResponse,
|
||||
PaginatedProcurementPlans,
|
||||
GetProcurementPlansParams,
|
||||
GetPlanRequirementsParams,
|
||||
UpdatePlanStatusParams,
|
||||
} from '../types/orders';
|
||||
|
||||
export class OrdersService {
|
||||
@@ -168,6 +181,127 @@ export class OrdersService {
|
||||
static async getServiceStatus(tenantId: string): Promise<ServiceStatus> {
|
||||
return apiClient.get<ServiceStatus>(`/tenants/${tenantId}/orders/status`);
|
||||
}
|
||||
|
||||
// ===== Procurement Planning Endpoints =====
|
||||
|
||||
/**
|
||||
* Get current procurement plan for today
|
||||
* GET /tenants/{tenant_id}/procurement/plans/current
|
||||
*/
|
||||
static async getCurrentProcurementPlan(tenantId: string): Promise<ProcurementPlanResponse | null> {
|
||||
return apiClient.get<ProcurementPlanResponse | null>(`/tenants/${tenantId}/procurement/plans/current`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get procurement plan by specific date
|
||||
* GET /tenants/{tenant_id}/procurement/plans/date/{plan_date}
|
||||
*/
|
||||
static async getProcurementPlanByDate(tenantId: string, planDate: string): Promise<ProcurementPlanResponse | null> {
|
||||
return apiClient.get<ProcurementPlanResponse | null>(`/tenants/${tenantId}/procurement/plans/date/${planDate}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get procurement plan by ID
|
||||
* GET /tenants/{tenant_id}/procurement/plans/id/{plan_id}
|
||||
*/
|
||||
static async getProcurementPlanById(tenantId: string, planId: string): Promise<ProcurementPlanResponse | null> {
|
||||
return apiClient.get<ProcurementPlanResponse | null>(`/tenants/${tenantId}/procurement/plans/id/${planId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* List procurement plans with filtering
|
||||
* GET /tenants/{tenant_id}/procurement/plans/
|
||||
*/
|
||||
static async getProcurementPlans(params: GetProcurementPlansParams): Promise<PaginatedProcurementPlans> {
|
||||
const { tenant_id, status, start_date, end_date, limit = 50, offset = 0 } = params;
|
||||
|
||||
const queryParams = new URLSearchParams({
|
||||
limit: limit.toString(),
|
||||
offset: offset.toString(),
|
||||
});
|
||||
|
||||
if (status) queryParams.append('status', status);
|
||||
if (start_date) queryParams.append('start_date', start_date);
|
||||
if (end_date) queryParams.append('end_date', end_date);
|
||||
|
||||
return apiClient.get<PaginatedProcurementPlans>(
|
||||
`/tenants/${tenant_id}/procurement/plans?${queryParams.toString()}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new procurement plan
|
||||
* POST /tenants/{tenant_id}/procurement/plans/generate
|
||||
*/
|
||||
static async generateProcurementPlan(tenantId: string, request: GeneratePlanRequest): Promise<GeneratePlanResponse> {
|
||||
return apiClient.post<GeneratePlanResponse>(`/tenants/${tenantId}/procurement/plans/generate`, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update procurement plan status
|
||||
* PUT /tenants/{tenant_id}/procurement/plans/{plan_id}/status
|
||||
*/
|
||||
static async updateProcurementPlanStatus(params: UpdatePlanStatusParams): Promise<ProcurementPlanResponse> {
|
||||
const { tenant_id, plan_id, status } = params;
|
||||
|
||||
const queryParams = new URLSearchParams({ status });
|
||||
|
||||
return apiClient.put<ProcurementPlanResponse>(
|
||||
`/tenants/${tenant_id}/procurement/plans/${plan_id}/status?${queryParams.toString()}`,
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get procurement dashboard data
|
||||
* GET /tenants/{tenant_id}/procurement/dashboard
|
||||
*/
|
||||
static async getProcurementDashboard(tenantId: string): Promise<ProcurementDashboardData | null> {
|
||||
return apiClient.get<ProcurementDashboardData | null>(`/tenants/${tenantId}/procurement/dashboard`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get requirements for a specific plan
|
||||
* GET /tenants/{tenant_id}/procurement/plans/{plan_id}/requirements
|
||||
*/
|
||||
static async getPlanRequirements(params: GetPlanRequirementsParams): Promise<ProcurementRequirementResponse[]> {
|
||||
const { tenant_id, plan_id, status, priority } = params;
|
||||
|
||||
const queryParams = new URLSearchParams();
|
||||
if (status) queryParams.append('status', status);
|
||||
if (priority) queryParams.append('priority', priority);
|
||||
|
||||
const url = `/tenants/${tenant_id}/procurement/plans/${plan_id}/requirements${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
|
||||
|
||||
return apiClient.get<ProcurementRequirementResponse[]>(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get critical requirements across all plans
|
||||
* GET /tenants/{tenant_id}/procurement/requirements/critical
|
||||
*/
|
||||
static async getCriticalRequirements(tenantId: string): Promise<ProcurementRequirementResponse[]> {
|
||||
return apiClient.get<ProcurementRequirementResponse[]>(`/tenants/${tenantId}/procurement/requirements/critical`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger daily scheduler manually
|
||||
* POST /tenants/{tenant_id}/procurement/scheduler/trigger
|
||||
*/
|
||||
static async triggerDailyScheduler(tenantId: string): Promise<{ success: boolean; message: string; tenant_id: string }> {
|
||||
return apiClient.post<{ success: boolean; message: string; tenant_id: string }>(
|
||||
`/tenants/${tenantId}/procurement/scheduler/trigger`,
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get procurement service health
|
||||
* GET /tenants/{tenant_id}/procurement/health
|
||||
*/
|
||||
static async getProcurementHealth(tenantId: string): Promise<{ status: string; service: string; procurement_enabled: boolean; timestamp: string }> {
|
||||
return apiClient.get<{ status: string; service: string; procurement_enabled: boolean; timestamp: string }>(`/tenants/${tenantId}/procurement/health`);
|
||||
}
|
||||
}
|
||||
|
||||
export default OrdersService;
|
||||
@@ -280,4 +280,243 @@ export interface UpdateOrderStatusParams {
|
||||
export interface GetDemandRequirementsParams {
|
||||
tenant_id: string;
|
||||
target_date: string;
|
||||
}
|
||||
|
||||
// ===== Procurement Types =====
|
||||
|
||||
export type ProcurementPlanType = 'regular' | 'emergency' | 'seasonal';
|
||||
export type ProcurementStrategy = 'just_in_time' | 'bulk' | 'mixed';
|
||||
export type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
|
||||
export type RequirementStatus = 'pending' | 'approved' | 'ordered' | 'partially_received' | 'received' | 'cancelled';
|
||||
export type PlanStatus = 'draft' | 'pending_approval' | 'approved' | 'in_execution' | 'completed' | 'cancelled';
|
||||
export type DeliveryStatus = 'pending' | 'in_transit' | 'delivered' | 'delayed' | 'cancelled';
|
||||
|
||||
// Procurement Requirement Types
|
||||
export interface ProcurementRequirementBase {
|
||||
product_id: string;
|
||||
product_name: string;
|
||||
product_sku?: string;
|
||||
product_category?: string;
|
||||
product_type: string;
|
||||
required_quantity: number;
|
||||
unit_of_measure: string;
|
||||
safety_stock_quantity: number;
|
||||
total_quantity_needed: number;
|
||||
current_stock_level: number;
|
||||
reserved_stock: number;
|
||||
available_stock: number;
|
||||
net_requirement: number;
|
||||
order_demand: number;
|
||||
production_demand: number;
|
||||
forecast_demand: number;
|
||||
buffer_demand: number;
|
||||
required_by_date: string;
|
||||
lead_time_buffer_days: number;
|
||||
suggested_order_date: string;
|
||||
latest_order_date: string;
|
||||
priority: PriorityLevel;
|
||||
risk_level: RiskLevel;
|
||||
preferred_supplier_id?: string;
|
||||
backup_supplier_id?: string;
|
||||
supplier_name?: string;
|
||||
supplier_lead_time_days?: number;
|
||||
minimum_order_quantity?: number;
|
||||
estimated_unit_cost?: number;
|
||||
estimated_total_cost?: number;
|
||||
last_purchase_cost?: number;
|
||||
}
|
||||
|
||||
export interface ProcurementRequirementCreate extends ProcurementRequirementBase {
|
||||
special_requirements?: string;
|
||||
storage_requirements?: string;
|
||||
shelf_life_days?: number;
|
||||
quality_specifications?: Record<string, any>;
|
||||
procurement_notes?: string;
|
||||
}
|
||||
|
||||
export interface ProcurementRequirementUpdate {
|
||||
status?: RequirementStatus;
|
||||
priority?: PriorityLevel;
|
||||
approved_quantity?: number;
|
||||
approved_cost?: number;
|
||||
purchase_order_id?: string;
|
||||
purchase_order_number?: string;
|
||||
ordered_quantity?: number;
|
||||
expected_delivery_date?: string;
|
||||
actual_delivery_date?: string;
|
||||
received_quantity?: number;
|
||||
delivery_status?: DeliveryStatus;
|
||||
procurement_notes?: string;
|
||||
}
|
||||
|
||||
export interface ProcurementRequirementResponse extends ProcurementRequirementBase {
|
||||
id: string;
|
||||
plan_id: string;
|
||||
requirement_number: string;
|
||||
status: RequirementStatus;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
purchase_order_id?: string;
|
||||
purchase_order_number?: string;
|
||||
ordered_quantity: number;
|
||||
ordered_at?: string;
|
||||
expected_delivery_date?: string;
|
||||
actual_delivery_date?: string;
|
||||
received_quantity: number;
|
||||
delivery_status: DeliveryStatus;
|
||||
fulfillment_rate?: number;
|
||||
on_time_delivery?: boolean;
|
||||
quality_rating?: number;
|
||||
approved_quantity?: number;
|
||||
approved_cost?: number;
|
||||
approved_at?: string;
|
||||
approved_by?: string;
|
||||
special_requirements?: string;
|
||||
storage_requirements?: string;
|
||||
shelf_life_days?: number;
|
||||
quality_specifications?: Record<string, any>;
|
||||
procurement_notes?: string;
|
||||
}
|
||||
|
||||
// Procurement Plan Types
|
||||
export interface ProcurementPlanBase {
|
||||
plan_date: string;
|
||||
plan_period_start: string;
|
||||
plan_period_end: string;
|
||||
planning_horizon_days: number;
|
||||
plan_type: ProcurementPlanType;
|
||||
priority: PriorityLevel;
|
||||
business_model?: BusinessModel;
|
||||
procurement_strategy: ProcurementStrategy;
|
||||
safety_stock_buffer: number;
|
||||
supply_risk_level: RiskLevel;
|
||||
demand_forecast_confidence?: number;
|
||||
seasonality_adjustment: number;
|
||||
special_requirements?: string;
|
||||
}
|
||||
|
||||
export interface ProcurementPlanCreate extends ProcurementPlanBase {
|
||||
tenant_id: string;
|
||||
requirements?: ProcurementRequirementCreate[];
|
||||
}
|
||||
|
||||
export interface ProcurementPlanUpdate {
|
||||
status?: PlanStatus;
|
||||
priority?: PriorityLevel;
|
||||
approved_at?: string;
|
||||
approved_by?: string;
|
||||
execution_started_at?: string;
|
||||
execution_completed_at?: string;
|
||||
special_requirements?: string;
|
||||
seasonal_adjustments?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface ProcurementPlanResponse extends ProcurementPlanBase {
|
||||
id: string;
|
||||
tenant_id: string;
|
||||
plan_number: string;
|
||||
status: PlanStatus;
|
||||
total_requirements: number;
|
||||
total_estimated_cost: number;
|
||||
total_approved_cost: number;
|
||||
cost_variance: number;
|
||||
total_demand_orders: number;
|
||||
total_demand_quantity: number;
|
||||
total_production_requirements: number;
|
||||
primary_suppliers_count: number;
|
||||
backup_suppliers_count: number;
|
||||
supplier_diversification_score?: number;
|
||||
approved_at?: string;
|
||||
approved_by?: string;
|
||||
execution_started_at?: string;
|
||||
execution_completed_at?: string;
|
||||
fulfillment_rate?: number;
|
||||
on_time_delivery_rate?: number;
|
||||
cost_accuracy?: number;
|
||||
quality_score?: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
created_by?: string;
|
||||
updated_by?: string;
|
||||
requirements: ProcurementRequirementResponse[];
|
||||
}
|
||||
|
||||
// Summary and Dashboard Types
|
||||
export interface ProcurementSummary {
|
||||
total_plans: number;
|
||||
active_plans: number;
|
||||
total_requirements: number;
|
||||
pending_requirements: number;
|
||||
critical_requirements: number;
|
||||
total_estimated_cost: number;
|
||||
total_approved_cost: number;
|
||||
cost_variance: number;
|
||||
average_fulfillment_rate?: number;
|
||||
average_on_time_delivery?: number;
|
||||
top_suppliers: Record<string, any>[];
|
||||
critical_items: Record<string, any>[];
|
||||
}
|
||||
|
||||
export interface ProcurementDashboardData {
|
||||
current_plan?: ProcurementPlanResponse;
|
||||
summary: ProcurementSummary;
|
||||
upcoming_deliveries: Record<string, any>[];
|
||||
overdue_requirements: Record<string, any>[];
|
||||
low_stock_alerts: Record<string, any>[];
|
||||
performance_metrics: Record<string, any>;
|
||||
}
|
||||
|
||||
// Request and Response Types
|
||||
export interface GeneratePlanRequest {
|
||||
plan_date?: string;
|
||||
force_regenerate: boolean;
|
||||
planning_horizon_days: number;
|
||||
include_safety_stock: boolean;
|
||||
safety_stock_percentage: number;
|
||||
}
|
||||
|
||||
export interface GeneratePlanResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
plan?: ProcurementPlanResponse;
|
||||
warnings: string[];
|
||||
errors: string[];
|
||||
}
|
||||
|
||||
export interface PaginatedProcurementPlans {
|
||||
plans: ProcurementPlanResponse[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
has_more: boolean;
|
||||
}
|
||||
|
||||
export interface ForecastRequest {
|
||||
target_date: string;
|
||||
horizon_days: number;
|
||||
include_confidence_intervals: boolean;
|
||||
product_ids?: string[];
|
||||
}
|
||||
|
||||
// Query Parameter Types for Procurement
|
||||
export interface GetProcurementPlansParams {
|
||||
tenant_id: string;
|
||||
status?: string;
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export interface GetPlanRequirementsParams {
|
||||
tenant_id: string;
|
||||
plan_id: string;
|
||||
status?: string;
|
||||
priority?: string;
|
||||
}
|
||||
|
||||
export interface UpdatePlanStatusParams {
|
||||
tenant_id: string;
|
||||
plan_id: string;
|
||||
status: PlanStatus;
|
||||
}
|
||||
Reference in New Issue
Block a user