/** * Purchase Orders API Client * Handles all API calls for purchase orders * * UPDATED in Sprint 3: Purchase orders now managed by Procurement Service * Previously: Suppliers Service (/tenants/{id}/purchase-orders) * Now: Procurement Service (/tenants/{id}/procurement/purchase-orders) */ import { apiClient } from '../client'; export type PurchaseOrderStatus = | 'DRAFT' | 'PENDING_APPROVAL' | 'APPROVED' | 'SENT_TO_SUPPLIER' | 'CONFIRMED' | 'RECEIVED' | 'COMPLETED' | 'CANCELLED' | 'DISPUTED'; export type PurchaseOrderPriority = 'urgent' | 'high' | 'normal' | 'low'; export interface PurchaseOrderItem { id: string; inventory_product_id: string; product_code?: string; product_name?: string; ordered_quantity: number; unit_of_measure: string; unit_price: string; // Decimal as string line_total: string; // Decimal as string received_quantity: number; remaining_quantity: number; quality_requirements?: string; item_notes?: string; } export interface SupplierSummary { id: string; name: string; supplier_code: string; supplier_type: string; status: string; contact_person?: string; email?: string; phone?: string; } export interface PurchaseOrderSummary { id: string; po_number: string; supplier_id: string; supplier_name?: string; status: PurchaseOrderStatus; priority: PurchaseOrderPriority; order_date: string; required_delivery_date?: string; total_amount: string; // Decimal as string currency: string; created_at: string; reasoning_data?: any; // AI reasoning data for dashboard display ai_reasoning_summary?: string; // Human-readable summary } export interface PurchaseOrderDetail extends PurchaseOrderSummary { reference_number?: string; estimated_delivery_date?: string; // Financial information subtotal: string; tax_amount: string; shipping_cost: string; discount_amount: string; // Delivery information delivery_address?: string; delivery_instructions?: string; delivery_contact?: string; delivery_phone?: string; // Approval workflow requires_approval: boolean; approved_by?: string; approved_at?: string; rejection_reason?: string; // Communication tracking sent_to_supplier_at?: string; supplier_confirmation_date?: string; supplier_reference?: string; // Additional information notes?: string; internal_notes?: string; terms_and_conditions?: string; // Audit fields updated_at: string; created_by: string; updated_by: string; // Related data supplier?: SupplierSummary; items?: PurchaseOrderItem[]; } export interface PurchaseOrderSearchParams { supplier_id?: string; status?: PurchaseOrderStatus; priority?: PurchaseOrderPriority; date_from?: string; // YYYY-MM-DD date_to?: string; // YYYY-MM-DD search_term?: string; limit?: number; skip?: number; // ✅ Changed from "offset" to "skip" to match backend } export interface PurchaseOrderUpdateData { status?: PurchaseOrderStatus; priority?: PurchaseOrderPriority; notes?: string; rejection_reason?: string; internal_notes?: string; } export interface PurchaseOrderItemCreate { inventory_product_id: string; ordered_quantity: number; unit_price: string; // Decimal as string unit_of_measure: string; quality_requirements?: string; item_notes?: string; } export interface PurchaseOrderCreateData { supplier_id: string; required_delivery_date?: string; priority?: PurchaseOrderPriority; tax_amount?: number; shipping_cost?: number; discount_amount?: number; notes?: string; procurement_plan_id?: string; items: PurchaseOrderItemCreate[]; } /** * Create a new purchase order */ export async function createPurchaseOrder( tenantId: string, data: PurchaseOrderCreateData ): Promise { return apiClient.post( `/tenants/${tenantId}/procurement/purchase-orders`, data ); } /** * Get list of purchase orders with optional filters */ export async function listPurchaseOrders( tenantId: string, params?: PurchaseOrderSearchParams ): Promise { return apiClient.get( `/tenants/${tenantId}/procurement/purchase-orders`, { params } ); } /** * Get purchase orders by status */ export async function getPurchaseOrdersByStatus( tenantId: string, status: PurchaseOrderStatus, limit: number = 50 ): Promise { return listPurchaseOrders(tenantId, { status, limit }); } /** * Get pending approval purchase orders */ export async function getPendingApprovalPurchaseOrders( tenantId: string, limit: number = 50 ): Promise { return getPurchaseOrdersByStatus(tenantId, 'PENDING_APPROVAL', limit); } /** * Get a single purchase order by ID with full details */ export async function getPurchaseOrder( tenantId: string, poId: string ): Promise { return apiClient.get( `/tenants/${tenantId}/procurement/purchase-orders/${poId}` ); } /** * Update purchase order */ export async function updatePurchaseOrder( tenantId: string, poId: string, data: PurchaseOrderUpdateData ): Promise { return apiClient.put( `/tenants/${tenantId}/procurement/purchase-orders/${poId}`, data ); } /** * Approve a purchase order */ export async function approvePurchaseOrder( tenantId: string, poId: string, notes?: string ): Promise { return apiClient.post( `/tenants/${tenantId}/procurement/purchase-orders/${poId}/approve`, { action: 'approve', notes: notes || 'Approved from dashboard' } ); } /** * Reject a purchase order */ export async function rejectPurchaseOrder( tenantId: string, poId: string, reason: string ): Promise { return apiClient.post( `/tenants/${tenantId}/procurement/purchase-orders/${poId}/approve`, { action: 'reject', notes: reason } ); } /** * Bulk approve purchase orders */ export async function bulkApprovePurchaseOrders( tenantId: string, poIds: string[], notes?: string ): Promise { const approvalPromises = poIds.map(poId => approvePurchaseOrder(tenantId, poId, notes) ); return Promise.all(approvalPromises); } /** * Delete purchase order */ export async function deletePurchaseOrder( tenantId: string, poId: string ): Promise<{ message: string }> { return apiClient.delete<{ message: string }>( `/tenants/${tenantId}/procurement/purchase-orders/${poId}` ); } // ================================================================ // DELIVERY TYPES AND METHODS // ================================================================ export interface DeliveryItemInput { purchase_order_item_id: string; inventory_product_id: string; ordered_quantity: number; delivered_quantity: number; accepted_quantity: number; rejected_quantity: number; batch_lot_number?: string; expiry_date?: string; quality_grade?: string; quality_issues?: string; rejection_reason?: string; item_notes?: string; } export interface CreateDeliveryInput { purchase_order_id: string; supplier_id: string; supplier_delivery_note?: string; scheduled_date?: string; estimated_arrival?: string; carrier_name?: string; tracking_number?: string; inspection_passed?: boolean; inspection_notes?: string; notes?: string; items: DeliveryItemInput[]; } export interface DeliveryResponse { id: string; tenant_id: string; purchase_order_id: string; supplier_id: string; delivery_number: string; status: string; scheduled_date?: string; estimated_arrival?: string; actual_arrival?: string; completed_at?: string; inspection_passed?: boolean; inspection_notes?: string; notes?: string; created_at: string; updated_at: string; } /** * Create delivery for purchase order */ export async function createDelivery( tenantId: string, poId: string, deliveryData: CreateDeliveryInput ): Promise { return apiClient.post( `/tenants/${tenantId}/procurement/purchase-orders/${poId}/deliveries`, deliveryData ); }