erp-core-frontend-web/src/services/api/purchases.api.ts
rckrdmrd f1a9ea3d1f [TASK-2026-01-20-004] feat: Add API clients for sales, purchases, financial, CRM, projects
EPIC-P1-004: Frontend API clients
- Add sales.api.ts (orders, quotations, returns)
- Add purchases.api.ts (purchase orders, suppliers, receipts)
- Add financial.api.ts (accounts, journals, payments)
- Add crm.api.ts (leads, opportunities, campaigns)
- Add projects.api.ts (projects, tasks, timesheets)
- Update api/index.ts with new exports

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 04:06:32 -06:00

280 lines
8.8 KiB
TypeScript

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<PurchaseOrderLine, 'id' | 'productName' | 'subtotal'>[];
notes?: string;
}
export interface UpdatePurchaseOrderDto {
partnerId?: string;
dateOrder?: string;
dateExpected?: string;
paymentTermId?: string;
warehouseId?: string;
lines?: Omit<PurchaseOrderLine, 'productName' | 'subtotal'>[];
notes?: string;
}
export interface CreatePurchaseRfqDto {
partnerId: string;
dateRfq?: string;
dateExpiry?: string;
paymentTermId?: string;
lines: Omit<PurchaseOrderLine, 'id' | 'productName' | 'subtotal'>[];
notes?: string;
}
export interface UpdatePurchaseRfqDto {
partnerId?: string;
dateRfq?: string;
dateExpiry?: string;
paymentTermId?: string;
lines?: Omit<PurchaseOrderLine, 'productName' | 'subtotal'>[];
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<PaginatedResponse<PurchaseOrder>> => {
const response = await api.get<PaginatedResponse<PurchaseOrder>>(
API_ENDPOINTS.PURCHASES.ORDERS,
{ params: filters }
);
return response.data;
},
getOrderById: async (id: string): Promise<PurchaseOrder> => {
const response = await api.get<ApiResponse<PurchaseOrder>>(
`${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<PurchaseOrder> => {
const response = await api.post<ApiResponse<PurchaseOrder>>(
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<PurchaseOrder> => {
const response = await api.patch<ApiResponse<PurchaseOrder>>(
`${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<PurchaseOrder> => {
const response = await api.post<ApiResponse<PurchaseOrder>>(
`${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<PurchaseOrder> => {
const response = await api.post<ApiResponse<PurchaseOrder>>(
`${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<PurchaseOrder> => {
const response = await api.post<ApiResponse<PurchaseOrder>>(
`${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<void> => {
const response = await api.delete<ApiResponse>(
`${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<PaginatedResponse<PurchaseRfq>> => {
const response = await api.get<PaginatedResponse<PurchaseRfq>>(
API_ENDPOINTS.PURCHASES.RFQS,
{ params: filters }
);
return response.data;
},
getRfqById: async (id: string): Promise<PurchaseRfq> => {
const response = await api.get<ApiResponse<PurchaseRfq>>(
`${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<PurchaseRfq> => {
const response = await api.post<ApiResponse<PurchaseRfq>>(
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<PurchaseRfq> => {
const response = await api.patch<ApiResponse<PurchaseRfq>>(
`${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<PurchaseRfq> => {
const response = await api.post<ApiResponse<PurchaseRfq>>(
`${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<PurchaseOrder> => {
const response = await api.post<ApiResponse<PurchaseOrder>>(
`${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<PurchaseRfq> => {
const response = await api.post<ApiResponse<PurchaseRfq>>(
`${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<void> => {
const response = await api.delete<ApiResponse>(
`${API_ENDPOINTS.PURCHASES.RFQS}/${id}`
);
if (!response.data.success) {
throw new Error(response.data.error || 'Error al eliminar solicitud de cotizacion');
}
},
};