Feat ERP 2

This commit is contained in:
2026-01-07 17:52:10 -03:00
parent fdb221d0fa
commit 29aa8e30e7
54 changed files with 3035 additions and 275 deletions

View File

@@ -0,0 +1,12 @@
import api from './api';
import type { Company } from '../types/Company';
export const companyService = {
/**
* Obtiene el listado de empresas activas para selectores.
*/
getAll: async (): Promise<Company[]> => {
const response = await api.get<Company[]>('/products/companies');
return response.data;
}
};

View File

@@ -0,0 +1,12 @@
import api from './api';
import type { ClientProfile } from '../types/Finance';
export const financeService = {
/**
* Obtiene el perfil financiero y la deuda actual de un cliente.
*/
getClientStatus: async (clientId: number): Promise<ClientProfile> => {
const response = await api.get<ClientProfile>(`/finance/client/${clientId}`);
return response.data;
}
};

View File

@@ -0,0 +1,32 @@
import api from './api';
import type { CreateOrderRequest, OrderResult } from '../types/Order';
export const orderService = {
/**
* Crea una orden de venta completa (Contado o Cta Cte)
*/
createOrder: async (request: CreateOrderRequest): Promise<OrderResult> => {
// Validaciones de seguridad antes de enviar
if (request.items.length === 0) throw new Error("La orden no puede estar vacía.");
if (request.clientId <= 0) throw new Error("Debe seleccionar un cliente.");
const response = await api.post<OrderResult>('/orders', request);
return response.data;
},
/**
* Obtiene el historial de órdenes de un cliente específico
*/
getByClient: async (clientId: number) => {
const response = await api.get(`/orders/client/${clientId}`);
return response.data;
},
/**
* Obtiene el detalle completo de una orden por ID
*/
getById: async (id: number) => {
const response = await api.get(`/orders/${id}`);
return response.data;
}
};

View File

@@ -0,0 +1,49 @@
import api from './api';
import type { Product, ProductBundleComponent } from '../types/Product';
export const productService = {
getAll: async (): Promise<Product[]> => {
const response = await api.get<Product[]>('/products');
return response.data;
},
getById: async (id: number): Promise<Product> => {
const response = await api.get<Product>(`/products/${id}`);
return response.data;
},
create: async (product: Partial<Product>): Promise<Product> => {
const response = await api.post<Product>('/products', product);
return response.data;
},
update: async (id: number, product: Partial<Product>): Promise<void> => {
await api.put(`/products/${id}`, product);
},
// --- GESTIÓN DE COMBOS (BUNDLES) ---
/**
* Agrega un producto hijo a un combo padre.
*/
addComponentToBundle: async (bundleId: number, component: { childProductId: number; quantity: number; fixedAllocationAmount?: number }) => {
await api.post(`/products/${bundleId}/components`, component);
},
/**
* Elimina un componente de un combo.
*/
removeComponentFromBundle: async (bundleId: number, childProductId: number) => {
// Nota: El backend espera el ID del producto hijo, no el ID de la relación,
// según nuestra implementación de 'RemoveComponentFromBundleAsync' en el repo.
await api.delete(`/products/${bundleId}/components/${childProductId}`);
},
/**
* Obtiene la lista de componentes que forman un combo.
*/
getBundleComponents: async (bundleId: number): Promise<ProductBundleComponent[]> => {
const response = await api.get<ProductBundleComponent[]>(`/products/${bundleId}/components`);
return response.data;
}
};