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 SalesOrderLine { id?: string; productId: string; productName?: string; quantity: number; unitPrice: number; discount?: number; taxIds?: string[]; subtotal?: number; } export interface SalesOrder extends BaseEntity { name: string; partnerId: string; partnerName?: string; dateOrder: string; dateDelivery?: string; status: 'draft' | 'confirmed' | 'done' | 'cancelled'; pricelistId?: string; paymentTermId?: string; warehouseId?: string; lines: SalesOrderLine[]; amountUntaxed: number; amountTax: number; amountTotal: number; notes?: string; tenantId: string; } export interface Quotation extends BaseEntity { name: string; partnerId: string; partnerName?: string; dateQuotation: string; dateExpiry?: string; status: 'draft' | 'sent' | 'confirmed' | 'cancelled' | 'expired'; pricelistId?: string; paymentTermId?: string; lines: SalesOrderLine[]; amountUntaxed: number; amountTax: number; amountTotal: number; notes?: string; tenantId: string; } // ============================================================================ // DTOs // ============================================================================ export interface CreateSalesOrderDto { partnerId: string; dateOrder?: string; dateDelivery?: string; pricelistId?: string; paymentTermId?: string; warehouseId?: string; lines: Omit[]; notes?: string; } export interface UpdateSalesOrderDto { partnerId?: string; dateOrder?: string; dateDelivery?: string; pricelistId?: string; paymentTermId?: string; warehouseId?: string; lines?: Omit[]; notes?: string; } export interface CreateQuotationDto { partnerId: string; dateQuotation?: string; dateExpiry?: string; pricelistId?: string; paymentTermId?: string; lines: Omit[]; notes?: string; } export interface UpdateQuotationDto { partnerId?: string; dateQuotation?: string; dateExpiry?: string; pricelistId?: string; paymentTermId?: string; lines?: Omit[]; notes?: string; } // ============================================================================ // Filters // ============================================================================ export interface SalesOrderFilters extends PaginationParams { partnerId?: string; status?: SalesOrder['status']; dateFrom?: string; dateTo?: string; } export interface QuotationFilters extends PaginationParams { partnerId?: string; status?: Quotation['status']; dateFrom?: string; dateTo?: string; } // ============================================================================ // API Client // ============================================================================ export const salesApi = { // Orders getOrders: async (filters?: SalesOrderFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.SALES.ORDERS, { params: filters } ); return response.data; }, getOrderById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.SALES.ORDERS}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Orden de venta no encontrada'); } return response.data.data; }, createOrder: async (data: CreateSalesOrderDto): Promise => { const response = await api.post>( API_ENDPOINTS.SALES.ORDERS, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear orden de venta'); } return response.data.data; }, updateOrder: async (id: string, data: UpdateSalesOrderDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.SALES.ORDERS}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar orden de venta'); } return response.data.data; }, confirmOrder: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.SALES.ORDERS}/${id}/confirm` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al confirmar orden de venta'); } return response.data.data; }, cancelOrder: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.SALES.ORDERS}/${id}/cancel` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al cancelar orden de venta'); } return response.data.data; }, deleteOrder: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.SALES.ORDERS}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar orden de venta'); } }, // Quotations getQuotations: async (filters?: QuotationFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.SALES.QUOTATIONS, { params: filters } ); return response.data; }, getQuotationById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.SALES.QUOTATIONS}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Cotizacion no encontrada'); } return response.data.data; }, createQuotation: async (data: CreateQuotationDto): Promise => { const response = await api.post>( API_ENDPOINTS.SALES.QUOTATIONS, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear cotizacion'); } return response.data.data; }, updateQuotation: async (id: string, data: UpdateQuotationDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.SALES.QUOTATIONS}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar cotizacion'); } return response.data.data; }, confirmQuotation: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.SALES.QUOTATIONS}/${id}/confirm` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al confirmar cotizacion'); } return response.data.data; }, sendQuotation: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.SALES.QUOTATIONS}/${id}/send` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al enviar cotizacion'); } return response.data.data; }, cancelQuotation: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.SALES.QUOTATIONS}/${id}/cancel` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al cancelar cotizacion'); } return response.data.data; }, deleteQuotation: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.SALES.QUOTATIONS}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar cotizacion'); } }, };