import api from './axios-instance'; import { API_ENDPOINTS } from '@shared/constants/api-endpoints'; import type { BaseEntity } from '@shared/types/entities.types'; import type { ApiResponse, PaginatedResponse, PaginationParams } from '@shared/types/api.types'; // ============================================================================ // Interfaces // ============================================================================ export interface PurchaseOrderLine { id?: string; productId: string; productName?: string; quantity: number; unitPrice: number; discount?: number; taxIds?: string[]; subtotal?: number; dateExpected?: string; } export interface PurchaseOrder extends BaseEntity { name: string; partnerId: string; partnerName?: string; dateOrder: string; dateExpected?: string; status: 'draft' | 'confirmed' | 'received' | 'done' | 'cancelled'; paymentTermId?: string; warehouseId?: string; lines: PurchaseOrderLine[]; amountUntaxed: number; amountTax: number; amountTotal: number; notes?: string; tenantId: string; } export interface PurchaseRfq extends BaseEntity { name: string; partnerId: string; partnerName?: string; dateRfq: string; dateExpiry?: string; status: 'draft' | 'sent' | 'confirmed' | 'cancelled' | 'expired'; paymentTermId?: string; lines: PurchaseOrderLine[]; amountUntaxed: number; amountTax: number; amountTotal: number; notes?: string; tenantId: string; } // ============================================================================ // DTOs // ============================================================================ export interface CreatePurchaseOrderDto { partnerId: string; dateOrder?: string; dateExpected?: string; paymentTermId?: string; warehouseId?: string; lines: Omit[]; notes?: string; } export interface UpdatePurchaseOrderDto { partnerId?: string; dateOrder?: string; dateExpected?: string; paymentTermId?: string; warehouseId?: string; lines?: Omit[]; notes?: string; } export interface CreatePurchaseRfqDto { partnerId: string; dateRfq?: string; dateExpiry?: string; paymentTermId?: string; lines: Omit[]; notes?: string; } export interface UpdatePurchaseRfqDto { partnerId?: string; dateRfq?: string; dateExpiry?: string; paymentTermId?: string; lines?: Omit[]; notes?: string; } // ============================================================================ // Filters // ============================================================================ export interface PurchaseOrderFilters extends PaginationParams { partnerId?: string; status?: PurchaseOrder['status']; dateFrom?: string; dateTo?: string; } export interface PurchaseRfqFilters extends PaginationParams { partnerId?: string; status?: PurchaseRfq['status']; dateFrom?: string; dateTo?: string; } // ============================================================================ // API Client // ============================================================================ export const purchasesApi = { // Orders getOrders: async (filters?: PurchaseOrderFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.PURCHASES.ORDERS, { params: filters } ); return response.data; }, getOrderById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.PURCHASES.ORDERS}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Orden de compra no encontrada'); } return response.data.data; }, createOrder: async (data: CreatePurchaseOrderDto): Promise => { const response = await api.post>( API_ENDPOINTS.PURCHASES.ORDERS, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear orden de compra'); } return response.data.data; }, updateOrder: async (id: string, data: UpdatePurchaseOrderDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.PURCHASES.ORDERS}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar orden de compra'); } return response.data.data; }, confirmOrder: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.PURCHASES.ORDERS}/${id}/confirm` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al confirmar orden de compra'); } return response.data.data; }, receiveOrder: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.PURCHASES.ORDERS}/${id}/receive` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al recibir orden de compra'); } return response.data.data; }, cancelOrder: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.PURCHASES.ORDERS}/${id}/cancel` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al cancelar orden de compra'); } return response.data.data; }, deleteOrder: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.PURCHASES.ORDERS}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar orden de compra'); } }, // RFQs (Request for Quotation) getRfqs: async (filters?: PurchaseRfqFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.PURCHASES.RFQS, { params: filters } ); return response.data; }, getRfqById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.PURCHASES.RFQS}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Solicitud de cotizacion no encontrada'); } return response.data.data; }, createRfq: async (data: CreatePurchaseRfqDto): Promise => { const response = await api.post>( API_ENDPOINTS.PURCHASES.RFQS, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear solicitud de cotizacion'); } return response.data.data; }, updateRfq: async (id: string, data: UpdatePurchaseRfqDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.PURCHASES.RFQS}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar solicitud de cotizacion'); } return response.data.data; }, sendRfq: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.PURCHASES.RFQS}/${id}/send` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al enviar solicitud de cotizacion'); } return response.data.data; }, confirmRfq: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.PURCHASES.RFQS}/${id}/confirm` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al confirmar solicitud de cotizacion'); } return response.data.data; }, cancelRfq: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.PURCHASES.RFQS}/${id}/cancel` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al cancelar solicitud de cotizacion'); } return response.data.data; }, deleteRfq: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.PURCHASES.RFQS}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar solicitud de cotizacion'); } }, };