---
name: shopify-valor-inventario
description: "Solo lectura: calcula el valor total de tu inventario (cantidad × costo) por ubicación y por proveedor, para contabilidad y seguros. Úsala cuando necesites el valor del inventario para el cierre del mes o para asegurar tu mercancía."
---

## Propósito
Calcula el valor total del inventario (cantidad en existencia × costo unitario) desglosado por ubicación y por proveedor. Sirve para la conciliación periódica del balance, la valoración para seguros y los reportes de costo de la mercancía vendida. Solo lectura: no ejecuta mutaciones.

## Requisitos
- Sesión autenticada de Shopify CLI: `shopify store auth --store <tu-tienda>.myshopify.com --scopes read_products,read_inventory`
- Las consultas se ejecutan con `shopify store execute`.
- Permisos (scopes) de la API: `read_products`, `read_inventory`
- Para que la valoración sea precisa, los artículos de inventario deben tener el costo unitario configurado (las variantes sin costo se incluyen con valor 0)

## Parámetros

| Parámetro | Tipo | Obligatorio | Por defecto | Descripción |
|-----------|------|-------------|-------------|-------------|
| store | string | sí | — | Dominio de la tienda (p. ej., tu-tienda.myshopify.com) |
| breakdown | string | no | both | Nivel de desglose: `location`, `vendor` o `both` |
| include_zero_cost | bool | no | true | Incluye los artículos sin costo configurado (aparecen con valor 0) |
| format | string | 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:** `locations` — consulta
   **Entradas:** `first: 50`, solo ubicaciones activas
   **Resultado esperado:** IDs y nombres de todas las ubicaciones activas

2. **OPERACIÓN:** `productVariants` — consulta
   **Entradas:** `first: 250`, selecciona `sku`, `inventoryQuantity`, `product { vendor }`, `inventoryItem { id, unitCost }`, cursor de paginación
   **Resultado esperado:** Todas las variantes con su costo y stock; pagina hasta que `hasNextPage: false`

3. **OPERACIÓN:** `inventoryItems` — consulta
   **Entradas:** Agrupa por IDs de artículos de inventario; trae `inventoryLevels` por ubicación
   **Resultado esperado:** Cantidades por ubicación de cada artículo de inventario

4. Calcula: para cada par (variante, ubicación): `value = quantity × unit_cost`; suma los resultados por ubicación y por proveedor

## Operaciones GraphQL

```graphql
# locations:query — validado con api_version 2025-01
query ActiveLocationsForValuation {
  locations(first: 50, includeInactive: false) {
    edges {
      node {
        id
        name
        isActive
      }
    }
  }
}
```

```graphql
# productVariants:query — validado con api_version 2025-01
query VariantsForValuation($after: String) {
  productVariants(first: 250, after: $after) {
    edges {
      node {
        id
        sku
        inventoryQuantity
        product {
          id
          title
          vendor
        }
        inventoryItem {
          id
          unitCost {
            amount
            currencyCode
          }
          tracked
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

```graphql
# inventoryItems:query — validado con api_version 2025-01
query InventoryLevelsByLocation($ids: [ID!]!) {
  nodes(ids: $ids) {
    ... on InventoryItem {
      id
      sku
      inventoryLevels(first: 20) {
        edges {
          node {
            location {
              id
              name
            }
            quantities(names: ["on_hand"]) {
              name
              quantity
            }
          }
        }
      }
    }
  }
}
```

## Seguimiento de la sesión

**Claude DEBE mostrar esta salida en cada etapa. Es obligatorio.**

**Al iniciar**, muestra:
```
╔══════════════════════════════════════════════╗
║  SKILL: Valor del inventario                 ║
║  Tienda: <dominio de la tienda>              ║
║  Inicio: <YYYY-MM-DD HH:MM UTC>              ║
╚══════════════════════════════════════════════╝
```

**Después de cada paso**, muestra:
```
[N/TOTAL] <CONSULTA|MUTACIÓN>  <NombreOperación>
          → Parámetros: <resumen breve de las entradas clave>
          → Resultado: <conteo o resultado>
```

**Al terminar**, muestra:

Para `format: human` (por defecto):
```
══════════════════════════════════════════════
REPORTE DE VALOR DEL INVENTARIO
  Valor total del inventario:  $<monto> <moneda>
  SKU incluidos:               <n>  (de los cuales <n> no tienen costo)

  Por ubicación:
    Bodega A             $<monto>
    Bodega B             $<monto>

  Por proveedor:
    Proveedor X          $<monto>
    Proveedor Y          $<monto>
  Archivo: inventory_valuation_<fecha>.csv
══════════════════════════════════════════════
```

Para `format: json`, muestra:
```json
{
  "skill": "shopify-valor-inventario",
  "store": "<dominio>",
  "total_value": 0,
  "currency": "<moneda de la tienda>",
  "skus_included": 0,
  "zero_cost_skus": 0,
  "by_location": [],
  "by_vendor": [],
  "output_file": "inventory_valuation_<fecha>.csv"
}
```

## Formato de salida
Archivo CSV `inventory_valuation_<YYYY-MM-DD>.csv` con las columnas:
`variant_id`, `sku`, `product_title`, `vendor`, `location`, `quantity_on_hand`, `unit_cost`, `total_value`, `currency`

## 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 |
| Sin costo unitario configurado | Variantes sin datos de costo | Inclúyelas con valor 0 y márcalas en el reporte |
| No hay ubicaciones activas | La tienda no tiene ubicaciones configuradas | Termina con un error |

## Buenas prácticas
- Córrela al cierre de cada mes para la conciliación del balance y compárala con tu sistema contable para encontrar diferencias.
- Los artículos sin costo aparecen con valor 0 y hacen que el valor total quede por debajo del real. Usa el resultado para identificar y completar los costos faltantes antes de la próxima ejecución.
- Para efectos de seguros, usa el valor total como base mínima del costo de reposición; agrega un margen para llevarlo a precio de venta si tu póliza lo exige.
- Combínala con `shopify-inventario-muerto` para entender qué parte del valor de tu inventario está atrapada en productos de baja rotación.
