Saltar al contenido principal

Stock de Productos por Almacén

Consulta la cantidad de stock disponible por producto en un almacén específico. Este endpoint es esencial para verificar disponibilidad antes de crear pedidos.

GET/v1/client/products/stock

Este endpoint te permite obtener la cantidad de stock disponible por producto en el almacén seleccionado. Es necesario proporcionar el header Authorization con el token Bearer obtenido previamente y también proporcionar un query param con el ID del almacén que quieres consultar.

Encabezados

ParámetroTipoRequeridoDescripción
Authorizationstring✅ SíToken Bearer obtenido del endpoint /token/generate

Parámetros de Query

ParámetroTipoRequeridoDescripción
warehouse_idinteger✅ SíID del almacén a consultar

Ejemplos

curl -X GET "https://apisandbox.eonwms.com/v1/client/products/stock?warehouse_id=1" \
-H "Authorization: Bearer TU_TOKEN"

Respuestas

200Éxito - Lista de productos con stock

{
"data": [
{
"id": "1",
"type": "product",
"attributes": {
"sku": "THISISSKU01",
"description": "WINGSPAN BOARDGAME",
"stock": {
"quantity": 997
}
}
},
{
"id": "2",
"type": "product",
"attributes": {
"sku": "THISISSKU2",
"description": "WINGSPAN OCEANIA EXPANTION",
"stock": {
"quantity": 500
}
}
}
]
}

401No autorizado - Token inválido

{
"code": 401,
"fault": {
"arguments": {
"Authorization": "invalid"
},
"type": "InvalidAuthorizationException",
"message": "La solicitud no está autorizada, el token de acceso es inválido."
}
}

422No procesable - Almacén inválido

{
"code": 422,
"fault": {
"arguments": {
"warehouse": "invalid"
},
"type": "warehouseParamIsInvalid",
"message": "el cliente no tiene acceso al almacén seleccionado."
}
}

Estructura de la Respuesta

Cada producto en el array data incluye:

Información del Producto

  • id: ID interno del producto
  • type: Siempre será "product"
  • attributes: Contiene los detalles del producto
    • sku: Código único del producto (Stock Keeping Unit)
    • description: Descripción del producto
    • stock: Información de inventario
      • quantity: Cantidad disponible en el almacén

Consideraciones de Stock

Stock en Tiempo Real

El stock mostrado es en tiempo real y considera:

  • ✅ Inventario físico disponible
  • ✅ Reservas de pedidos en proceso
  • ✅ Ajustes de inventario recientes

Stock NO Incluye

  • ❌ Productos en tránsito al almacén
  • ❌ Productos dañados o en cuarentena
  • ❌ Reservas futuras programadas

Casos de Uso Comunes

1. Verificación Pre-Pedido

async function validarDisponibilidadPedido(warehouseId, productos) {
// Obtener stock actual
const response = await fetch(
`https://apisandbox.eonwms.com/v1/client/products/stock?warehouse_id=${warehouseId}`,
{
headers: { 'Authorization': 'Bearer TU_TOKEN' }
}
);

const stockData = await response.json();
const problemas = [];

// Verificar cada producto del pedido
for (const item of productos) {
const productoEnStock = stockData.data.find(
p => p.attributes.sku === item.sku
);

if (!productoEnStock) {
problemas.push({
sku: item.sku,
tipo: 'NO_EXISTE',
mensaje: `El producto ${item.sku} no existe en el almacén`
});
continue;
}

const disponible = productoEnStock.attributes.stock.quantity;

if (disponible < item.cantidad) {
problemas.push({
sku: item.sku,
tipo: 'STOCK_INSUFICIENTE',
mensaje: `Solo hay ${disponible} unidades disponibles, se requieren ${item.cantidad}`,
disponible,
requerido: item.cantidad,
faltante: item.cantidad - disponible
});
}
}

return {
pedidoValido: problemas.length === 0,
problemas
};
}

2. Monitor de Stock Bajo

async function monitorearStockBajo(warehouseId, umbralMinimo = 10) {
const response = await fetch(
`https://apisandbox.eonwms.com/v1/client/products/stock?warehouse_id=${warehouseId}`,
{
headers: { 'Authorization': 'Bearer TU_TOKEN' }
}
);

const stockData = await response.json();

const productosConStockBajo = stockData.data
.filter(p => p.attributes.stock.quantity <= umbralMinimo)
.map(p => ({
sku: p.attributes.sku,
descripcion: p.attributes.description,
stockActual: p.attributes.stock.quantity,
estado: p.attributes.stock.quantity === 0 ? 'AGOTADO' : 'STOCK_BAJO'
}));

if (productosConStockBajo.length > 0) {
console.log(`⚠️ Alerta: ${productosConStockBajo.length} productos con stock bajo`);
productosConStockBajo.forEach(p => {
console.log(`- ${p.sku}: ${p.stockActual} unidades (${p.estado})`);
});
}

return productosConStockBajo;
}

3. Reporte de Inventario

async function generarReporteInventario(warehouseId) {
const response = await fetch(
`https://apisandbox.eonwms.com/v1/client/products/stock?warehouse_id=${warehouseId}`,
{
headers: { 'Authorization': 'Bearer TU_TOKEN' }
}
);

const stockData = await response.json();

// Calcular métricas
const totalSKUs = stockData.data.length;
const totalUnidades = stockData.data.reduce(
(sum, p) => sum + p.attributes.stock.quantity, 0
);
const skusAgotados = stockData.data.filter(
p => p.attributes.stock.quantity === 0
).length;
const skusConStock = totalSKUs - skusAgotados;

// Generar reporte
const reporte = {
almacen: warehouseId,
fecha: new Date().toISOString(),
resumen: {
totalSKUs,
skusConStock,
skusAgotados,
totalUnidades,
porcentajeDisponibilidad: ((skusConStock / totalSKUs) * 100).toFixed(2) + '%'
},
detalleProductos: stockData.data.map(p => ({
sku: p.attributes.sku,
descripcion: p.attributes.description,
stock: p.attributes.stock.quantity,
estado: p.attributes.stock.quantity === 0 ? 'Agotado' :
p.attributes.stock.quantity < 10 ? 'Stock Bajo' : 'Disponible'
}))
};

return reporte;
}

4. Sincronización con Sistema Externo

class SincronizadorInventario {
constructor(token, warehouseId) {
this.token = token;
this.warehouseId = warehouseId;
}

async obtenerStockChronos() {
const response = await fetch(
`https://apisandbox.eonwms.com/v1/client/products/stock?warehouse_id=${this.warehouseId}`,
{
headers: { 'Authorization': `Bearer ${this.token}` }
}
);

return await response.json();
}

async sincronizarConSistemaLocal(actualizarCallback) {
try {
const stockChronos = await this.obtenerStockChronos();

for (const producto of stockChronos.data) {
const { sku, stock } = producto.attributes;

// Actualizar sistema local
await actualizarCallback(sku, stock.quantity);
}

return {
exito: true,
productosSincronizados: stockChronos.data.length
};
} catch (error) {
return {
exito: false,
error: error.message
};
}
}
}

// Uso
const sincronizador = new SincronizadorInventario('TU_TOKEN', 1);

await sincronizador.sincronizarConSistemaLocal(async (sku, cantidad) => {
// Actualizar tu base de datos local
await db.productos.update({ sku }, { stockChronos: cantidad });
});

Mejores Prácticas

Frecuencia de Consulta

  • Antes de cada pedido: Siempre verifica el stock
  • Actualizaciones periódicas: Cada 15-30 minutos para sincronización
  • Alertas: Configura verificaciones cada hora para productos críticos

Manejo de Stock Cero

function manejarStockAgotado(sku, alternativas = []) {
// Opciones cuando no hay stock:

// 1. Buscar en otros almacenes
const buscarEnOtrosAlmacenes = async () => {
const warehouses = await obtenerAlmacenesDisponibles();
for (const wh of warehouses) {
const stock = await verificarStock(wh.id, sku);
if (stock > 0) return { almacenId: wh.id, stock };
}
return null;
};

// 2. Sugerir productos alternativos
const sugerirAlternativas = () => {
return alternativas.filter(alt => alt.stock > 0);
};

// 3. Permitir backorder (si está habilitado)
const permitirBackorder = () => {
return {
mensaje: "Producto disponible para pedido. Tiempo de entrega extendido.",
tiempoEstimado: "7-10 días"
};
};
}
Optimización de Consultas

Si necesitas verificar múltiples SKUs, es más eficiente hacer una sola consulta y filtrar localmente en lugar de hacer múltiples llamadas por SKU individual.

Sincronización de Stock

El stock puede cambiar rápidamente. Siempre verifica la disponibilidad justo antes de crear un pedido, no confíes en datos cacheados por mucho tiempo.

Stock Reservado

Cuando creas un pedido, el stock se reserva automáticamente. Si el pedido se cancela o no se procesa, el stock se libera después de un tiempo determinado.