Files
bakery-ia/frontend/src/api/services/procurement-service.ts

336 lines
11 KiB
TypeScript
Raw Normal View History

2025-11-01 21:35:03 +01:00
// ================================================================
// frontend/src/api/services/procurement-service.ts
// ================================================================
/**
* Procurement Service - Fully aligned with backend Procurement Service API
*
* Backend API: services/procurement/app/api/
* - procurement_plans.py: Plan CRUD and generation
* - analytics.py: Analytics and dashboard
* - purchase_orders.py: PO creation from plans
*
* Base URL: /api/v1/tenants/{tenant_id}/procurement/*
*
* Last Updated: 2025-10-31
* Status: Complete - 100% backend alignment
*/
import { apiClient } from '../client/apiClient';
import {
// Procurement Plan types
ProcurementPlanResponse,
ProcurementPlanCreate,
ProcurementPlanUpdate,
PaginatedProcurementPlans,
// Procurement Requirement types
ProcurementRequirementResponse,
ProcurementRequirementUpdate,
// Dashboard & Analytics types
ProcurementDashboardData,
ProcurementTrendsData,
// Request/Response types
GeneratePlanRequest,
GeneratePlanResponse,
AutoGenerateProcurementRequest,
AutoGenerateProcurementResponse,
CreatePOsResult,
LinkRequirementToPORequest,
UpdateDeliveryStatusRequest,
ApprovalRequest,
RejectionRequest,
// Query parameter types
GetProcurementPlansParams,
GetPlanRequirementsParams,
UpdatePlanStatusParams,
} from '../types/procurement';
/**
* Procurement Service
* All methods use the standalone Procurement Service backend API
*/
export class ProcurementService {
// ===================================================================
// ANALYTICS & DASHBOARD
// Backend: services/procurement/app/api/analytics.py
// ===================================================================
/**
* Get procurement analytics dashboard data
* GET /api/v1/tenants/{tenant_id}/procurement/analytics/procurement
*/
static async getProcurementAnalytics(tenantId: string): Promise<ProcurementDashboardData> {
return apiClient.get<ProcurementDashboardData>(`/tenants/${tenantId}/procurement/analytics/procurement`);
}
/**
* Get procurement time-series trends for charts
* GET /api/v1/tenants/{tenant_id}/procurement/analytics/procurement/trends
*/
static async getProcurementTrends(tenantId: string, days: number = 7): Promise<ProcurementTrendsData> {
return apiClient.get<ProcurementTrendsData>(`/tenants/${tenantId}/procurement/analytics/procurement/trends?days=${days}`);
}
// ===================================================================
// PROCUREMENT PLAN GENERATION
// Backend: services/procurement/app/api/procurement_plans.py
// ===================================================================
/**
* Auto-generate procurement plan from forecast data (Orchestrator integration)
* POST /api/v1/tenants/{tenant_id}/procurement/auto-generate
*
* Called by Orchestrator Service to create procurement plans based on forecast data
*/
static async autoGenerateProcurement(
tenantId: string,
request: AutoGenerateProcurementRequest
): Promise<AutoGenerateProcurementResponse> {
return apiClient.post<AutoGenerateProcurementResponse>(
`/tenants/${tenantId}/procurement/auto-generate`,
request
);
}
/**
* Generate a new procurement plan (manual/UI-driven)
* POST /api/v1/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
);
}
// ===================================================================
// PROCUREMENT PLAN CRUD
// Backend: services/procurement/app/api/procurement_plans.py
// ===================================================================
/**
* Get the current day's procurement plan
* GET /api/v1/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 ID
* GET /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}
*/
static async getProcurementPlanById(
tenantId: string,
planId: string
): Promise<ProcurementPlanResponse | null> {
return apiClient.get<ProcurementPlanResponse | null>(
`/tenants/${tenantId}/procurement/plans/${planId}`
);
}
/**
* Get procurement plan for a specific date
* GET /api/v1/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}`
);
}
/**
* List all procurement plans for tenant with pagination and filtering
* GET /api/v1/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()}`
);
}
/**
* Update procurement plan status
* PATCH /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/status
*/
static async updateProcurementPlanStatus(params: UpdatePlanStatusParams): Promise<ProcurementPlanResponse> {
const { tenant_id, plan_id, status, notes } = params;
const queryParams = new URLSearchParams({ status });
if (notes) queryParams.append('notes', notes);
return apiClient.patch<ProcurementPlanResponse>(
`/tenants/${tenant_id}/procurement/plans/${plan_id}/status?${queryParams.toString()}`,
{}
);
}
// ===================================================================
// PROCUREMENT REQUIREMENTS
// Backend: services/procurement/app/api/procurement_plans.py
// ===================================================================
/**
* Get all requirements for a procurement plan
* GET /api/v1/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 /api/v1/tenants/{tenant_id}/procurement/requirements/critical
*/
static async getCriticalRequirements(tenantId: string): Promise<ProcurementRequirementResponse[]> {
return apiClient.get<ProcurementRequirementResponse[]>(
`/tenants/${tenantId}/procurement/requirements/critical`
);
}
/**
* Link a procurement requirement to a purchase order
* POST /api/v1/tenants/{tenant_id}/procurement/requirements/{requirement_id}/link-purchase-order
*/
static async linkRequirementToPurchaseOrder(
tenantId: string,
requirementId: string,
request: LinkRequirementToPORequest
): Promise<{ success: boolean; message: string; requirement_id: string; purchase_order_id: string }> {
return apiClient.post<{
success: boolean;
message: string;
requirement_id: string;
purchase_order_id: string;
}>(
`/tenants/${tenantId}/procurement/requirements/${requirementId}/link-purchase-order`,
request
);
}
/**
* Update delivery status for a requirement
* PUT /api/v1/tenants/{tenant_id}/procurement/requirements/{requirement_id}/delivery-status
*/
static async updateRequirementDeliveryStatus(
tenantId: string,
requirementId: string,
request: UpdateDeliveryStatusRequest
): Promise<{ success: boolean; message: string; requirement_id: string; delivery_status: string }> {
return apiClient.put<{
success: boolean;
message: string;
requirement_id: string;
delivery_status: string;
}>(
`/tenants/${tenantId}/procurement/requirements/${requirementId}/delivery-status`,
request
);
}
// ===================================================================
// ADVANCED PROCUREMENT OPERATIONS
// Backend: services/procurement/app/api/procurement_plans.py
// ===================================================================
/**
* Recalculate an existing procurement plan
* POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/recalculate
*/
static async recalculateProcurementPlan(
tenantId: string,
planId: string
): Promise<GeneratePlanResponse> {
return apiClient.post<GeneratePlanResponse>(
`/tenants/${tenantId}/procurement/plans/${planId}/recalculate`,
{}
);
}
/**
* Approve a procurement plan with optional notes
* POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/approve
*/
static async approveProcurementPlan(
tenantId: string,
planId: string,
request?: ApprovalRequest
): Promise<ProcurementPlanResponse> {
return apiClient.post<ProcurementPlanResponse>(
`/tenants/${tenantId}/procurement/plans/${planId}/approve`,
request || {}
);
}
/**
* Reject a procurement plan with optional notes
* POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/reject
*/
static async rejectProcurementPlan(
tenantId: string,
planId: string,
request?: RejectionRequest
): Promise<ProcurementPlanResponse> {
return apiClient.post<ProcurementPlanResponse>(
`/tenants/${tenantId}/procurement/plans/${planId}/reject`,
request || {}
);
}
// ===================================================================
// PURCHASE ORDERS
// Backend: services/procurement/app/api/purchase_orders.py
// ===================================================================
/**
* Create purchase orders from procurement plan requirements
* Groups requirements by supplier and creates POs
* POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/create-purchase-orders
*/
static async createPurchaseOrdersFromPlan(
tenantId: string,
planId: string,
autoApprove: boolean = false
): Promise<CreatePOsResult> {
return apiClient.post<CreatePOsResult>(
`/tenants/${tenantId}/procurement/plans/${planId}/create-purchase-orders`,
{ auto_approve: autoApprove }
);
}
}
export default ProcurementService;