---
name: shopify-pronostico-demanda
description: "Solo lectura: pronostica la demanda de cada SKU según su ritmo de ventas y su tendencia, y calcula cuándo y cuánto pedirle al proveedor. Úsala para planear tus órdenes de compra y no quedarte sin stock."
---

## Propósito
Pronostica la demanda futura de cada SKU a partir de su velocidad de venta histórica, un análisis de tendencia y ajustes opcionales por temporada. Calcula el punto de reorden (cuándo pedir) y la cantidad sugerida de reorden (cuánto pedir), teniendo en cuenta el tiempo de entrega del proveedor y el stock de seguridad. Solo lectura: no ejecuta mutaciones.

## Requisitos
- Sesión autenticada de Shopify CLI: `shopify store auth --store <tu-tienda>.myshopify.com --scopes read_orders,read_products,read_inventory`
- Las consultas se ejecutan con `shopify store execute`.
- Permisos de la API: `read_orders`, `read_products`, `read_inventory`

## Parámetros

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|-------------|----------------|-------------|
| store | texto | sí | — | Dominio de la tienda |
| days_back | entero | no | 90 | Ventana histórica de ventas para calcular la velocidad |
| forecast_days | entero | no | 30 | Días hacia adelante para pronosticar la demanda |
| lead_time_days | entero | no | 14 | Tiempo de entrega predeterminado del proveedor, en días |
| safety_stock_days | entero | no | 7 | Días extra de stock de seguridad |
| vendor_filter | texto | no | — | Limita el análisis a un proveedor específico |
| only_low_stock | booleano | no | false | Muestra solo los artículos que se agotarían dentro de la ventana de pronóstico |
| format | texto | no | human | Formato de salida: `human` o `json` |

## Seguridad

> ℹ️ Skill de solo lectura: no ejecuta mutaciones. Puedes correrla en cualquier momento.

## Pasos

1. **OPERACIÓN:** `orders` — consulta
   **Entradas:** `query: "created_at:>='<HOY - days_back días>'"`, `first: 250`; selecciona `createdAt`, `lineItems { variant { id }, quantity }` y el cursor de paginación
   **Resultado esperado:** Todos los pedidos con sus líneas, para calcular la velocidad de venta

2. Calcula la velocidad de venta por variante:
   - Ventas diarias = total de unidades vendidas / days_back
   - Tendencia semanal: compara los últimos 30 días con los 30 días anteriores para saber hacia dónde va
   - Demanda pronosticada = daily_rate × forecast_days × trend_multiplier

3. **OPERACIÓN:** `productVariants` — consulta
   **Entradas:** Todos los IDs de variantes con historial de ventas, `first: 250` y el cursor de paginación
   **Resultado esperado:** Detalle de cada variante (SKU, título, título del producto, proveedor)

4. **OPERACIÓN:** `inventoryLevels` — consulta
   **Entradas:** IDs de los artículos de inventario de las variantes con stock
   **Resultado esperado:** Cantidades disponibles actuales por ubicación

5. Calcula las métricas de reorden:
   - **Días de stock** = current_inventory / daily_sales_rate
   - **Punto de reorden** = (lead_time_days + safety_stock_days) × daily_sales_rate
   - **Cantidad a pedir** = forecast_days × daily_sales_rate + safety_stock - current_inventory
   - **Fecha de agotamiento** = hoy + (current_inventory / daily_sales_rate) días
   - **Pedir a más tardar** = stockout_date - lead_time_days

6. Ordena por urgencia: primero los artículos que están más cerca de agotarse

## Operaciones GraphQL

```graphql
# orders:query — validada con api_version 2025-01
query SalesHistory($query: String!, $after: String) {
  orders(first: 250, after: $after, query: $query) {
    edges {
      node {
        createdAt
        lineItems(first: 50) {
          edges {
            node {
              quantity
              variant { id }
            }
          }
        }
      }
    }
    pageInfo { hasNextPage endCursor }
  }
}
```

```graphql
# productVariants:query — validada con api_version 2025-01
query VariantInfo($ids: [ID!]!) {
  nodes(ids: $ids) {
    ... on ProductVariant {
      id
      sku
      title
      product { id title vendor }
      inventoryQuantity
      inventoryItem { id }
    }
  }
}
```

```graphql
# inventoryItems:query — validada con api_version 2025-01
query InventoryItemDetails($ids: [ID!]!) {
  nodes(ids: $ids) {
    ... on InventoryItem {
      id
      unitCost { amount currencyCode }
      tracked
      inventoryLevels(first: 10) {
        edges {
          node {
            quantities(names: ["available"]) {
              name
              quantity
            }
            location { id name }
          }
        }
      }
    }
  }
}
```

```graphql
# inventoryLevels:query — validada con api_version 2025-01
query LocationInventory($locationId: ID!, $after: String) {
  location(id: $locationId) {
    inventoryLevels(first: 250, after: $after) {
      edges {
        node {
          quantities(names: ["available"]) { name quantity }
          item { id variant { id sku product { title } } }
        }
      }
      pageInfo { hasNextPage endCursor }
    }
  }
}
```

## Seguimiento de la sesión

**Claude DEBE mostrar la siguiente salida en cada etapa. Es obligatorio.**

**Al iniciar**, muestra:
```
╔══════════════════════════════════════════════╗
║  SKILL: Pronóstico de demanda y reorden      ║
║  Tienda: <dominio de la tienda>              ║
║  Inicio: <YYYY-MM-DD HH:MM UTC>              ║
╚══════════════════════════════════════════════╝
```

**Después de cada paso**, muestra:
```
[N/TOTAL] <QUERY|MUTATION>  <OperationName>
          → Parámetros: <resumen breve de las entradas clave>
          → Resultado: <cantidad o desenlace>
```

**Al terminar**, muestra:

Para `format: human` (predeterminado):
```
══════════════════════════════════════════════
PRONÓSTICO DE DEMANDA Y PLAN DE REORDEN  (<days_back>d de historial → <forecast_days>d de pronóstico)
  SKU analizados:           <n>
  Velocidad diaria prom.:   <n> unidades/día
  ─────────────────────────────
  ⚠️  URGENTE (se agota en <7 días):
    "<producto>" SKU:<sku>  Stock:<n>  Días restantes:<n>  PEDIR A MÁS TARDAR: <fecha>
    Cantidad a pedir: <n> unidades  Costo est.: $<n>

  ⏰ PLANEA CON TIEMPO (se agota en 7-30 días):
    "<producto>" SKU:<sku>  Stock:<n>  Días restantes:<n>  PEDIR A MÁS TARDAR: <fecha>

  ✅ SALUDABLE (>30 días de stock):
    <n> SKU con stock suficiente

  Archivo: reorder_plan_<fecha>.csv
══════════════════════════════════════════════
```

Para `format: json`, muestra:
```json
{
  "skill": "shopify-pronostico-demanda",
  "store": "<dominio>",
  "history_days": 90,
  "forecast_days": 30,
  "lead_time_days": 14,
  "skus_analyzed": 0,
  "urgent_reorders": [],
  "planned_reorders": [],
  "healthy_skus": 0,
  "output_file": "reorder_plan_<fecha>.csv"
}
```

## Formato de salida
Archivo CSV `reorder_plan_<YYYY-MM-DD>.csv` con las columnas:
`variant_id`, `sku`, `product_title`, `vendor`, `current_stock`, `daily_velocity`, `trend`, `days_of_stock`, `stockout_date`, `reorder_point`, `reorder_qty`, `order_by_date`, `est_cost`

## Manejo de errores
| Error | Causa | Solución |
|-------|-------|----------|
| `THROTTLED` | Se superó el límite de solicitudes de la API | Espera 2 segundos y reintenta hasta 3 veces |
| Velocidad de venta en cero | El producto no se vendió en la ventana | Exclúyelo del cálculo de reorden y márcalo como "sin datos de demanda" |
| Sin seguimiento de inventario | La variante no tiene seguimiento de inventario | Omítela: no se puede pronosticar un artículo sin seguimiento |

## Buenas prácticas
- Si puedes, define `lead_time_days` por proveedor; el valor predeterminado de 14 es conservador.
- Usa `safety_stock_days: 14` para artículos de alto valor o que tardan en llegar.
- Córrela cada semana y pasa el resultado a tu flujo de órdenes de compra.
- Crúzala con `shopify-velocidad-de-venta` para validar la velocidad.
- Úsala junto con `shopify-inventario-muerto` para no volver a pedir artículos que no se están vendiendo.
- Para productos de temporada, usa un `days_back` más largo (180-365) para capturar los patrones de temporada.
