---
name: shopify-resumen-despachos
description: "Genera un resumen diario de despachos: todos los pedidos abiertos agrupados por cuántos días llevan esperando, con los retenidos o con excepciones marcados. Úsala cada mañana para saber qué pedidos atender primero."
---

## Propósito
Produce un resumen diario de operaciones con todos los pedidos sin preparar y parcialmente preparados, agrupados según cuánto tiempo llevan esperando. Marca los pedidos con retenciones activas. Reemplaza el proceso manual de recorrer la página de Pedidos del admin de Shopify buscando pedidos atrasados y excepciones: esta skill trae cada pedido abierto, calcula su antigüedad, lo ubica en tramos de tiempo configurables y muestra los pedidos que tienen una retención de preparación activa. Así el equipo de operaciones tiene la cola completa de excepciones en una sola operación de solo lectura.

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

## Parámetros

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|-------------|----------------|-------------|
| store | string | sí | — | Dominio de la tienda (p. ej., mitienda.myshopify.com) |
| format | string | no | human | Formato de salida: `human` o `json` |
| dry_run | bool | no | false | Muestra una vista previa de las operaciones sin ejecutar cambios |
| aging_thresholds_days | array | no | [1, 3, 7] | Límites en días de los tramos de antigüedad (p. ej., `[1,3,7]` crea: 0–1 d, 1–3 d, 3–7 d, 7 d o más) |
| include_holds | bool | no | true | Incluye en una sección aparte los pedidos con retenciones de preparación activas |
| limit | integer | no | 250 | Máximo de pedidos a traer por página |

## Pasos

1. **OPERACIÓN:** `orders` — query
   **Entradas:** `first: <limit>`, `query: "fulfillment_status:unfulfilled OR fulfillment_status:partial"`, orden por `CREATED_AT` ascendente (los más antiguos primero), pagina hasta terminar
   **Resultado esperado:** Todos los pedidos abiertos con `createdAt`, `name`, `displayFulfillmentStatus`; calcula la antigüedad = ahora − `createdAt` en días; ubica cada pedido en los tramos de aging_thresholds_days

2. **OPERACIÓN:** `fulfillmentOrders` — query (a través del campo anidado `order.fulfillmentOrders`)
   **Entradas:** Para cada pedido del paso 1: `fulfillmentOrders(first: 5)` para revisar `status` y `requestStatus`; marca los que tengan `status: ON_HOLD`
   **Resultado esperado:** Estado de retención por pedido y `holdUntil` si existe; alimenta la sección de Retenidos del resumen

## Operaciones GraphQL

```graphql
# orders:query — validado con api_version 2025-01
query FulfillmentStatusDigest($first: Int!, $after: String, $query: String) {
  orders(first: $first, after: $after, query: $query, sortKey: CREATED_AT) {
    edges {
      node {
        id
        name
        createdAt
        displayFulfillmentStatus
        displayFinancialStatus
        totalPriceSet {
          shopMoney { amount currencyCode }
        }
        customer {
          id
          firstName
          lastName
        }
        fulfillmentOrders(first: 5) {
          edges {
            node {
              id
              status
              requestStatus
              fulfillAt
            }
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

Nota: `fulfillmentOrders` es un campo anidado del tipo `Order`; la operación `fulfillmentOrders:query` del paso 2 indica que se leen datos de las órdenes de preparación dentro de esta misma consulta.

## Seguimiento de la sesión

**Claude DEBE mostrar lo siguiente en cada etapa. Es obligatorio.**

**Al iniciar**, muestra:
```
╔══════════════════════════════════════════════╗
║  SKILL: Resumen diario de despachos          ║
║  Tienda: <dominio de la tienda>              ║
║  Inicio: <AAAA-MM-DD HH:MM UTC>              ║
╚══════════════════════════════════════════════╝
```

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

**Al terminar**, muestra:

Para `format: human` (predeterminado):
```
══════════════════════════════════════════════
RESUMEN DEL RESULTADO
  Total de pedidos abiertos:  <n>
  Tramo de antigüedad 0-1 d:  <n>
  Tramo de antigüedad 1-3 d:  <n>
  Tramo de antigüedad 3-7 d:  <n>
  Tramo de antigüedad 7 d+:   <n>
  Pedidos retenidos:          <n>
  Errores:                    0
  Archivo:                    ninguno
══════════════════════════════════════════════
```

Para `format: json`, muestra:
```json
{
  "skill": "shopify-resumen-despachos",
  "store": "<dominio>",
  "started_at": "<ISO8601>",
  "completed_at": "<ISO8601>",
  "dry_run": false,
  "steps": [
    { "step": 1, "operation": "FulfillmentStatusDigest", "type": "query", "params_summary": "limit: <n>, query: fulfillment_status:unfulfilled OR partial", "result_summary": "<n> pedidos obtenidos", "skipped": false },
    { "step": 2, "operation": "fulfillmentOrders", "type": "query", "params_summary": "anidado por pedido, first: 5", "result_summary": "<n> pedidos retenidos", "skipped": false }
  ],
  "outcome": {
    "total_open_orders": 0,
    "buckets": [
      { "label": "0-1d", "count": 0 },
      { "label": "1-3d", "count": 0 },
      { "label": "3-7d", "count": 0 },
      { "label": "7d+", "count": 0 }
    ],
    "orders_on_hold": 0,
    "errors": 0,
    "output_file": null
  }
}
```

## Formato de salida

**Resumen de antigüedad de despachos — `<store>` — `<fecha>`**
| Tramo de antigüedad | Cantidad de pedidos | Pedido más antiguo |
|---------------------|---------------------|--------------------|
| 0–1 días | n | #XXXX |
| 1–3 días | n | #XXXX |
| 3–7 días | n | #XXXX |
| 7+ días  | n | #XXXX (⚠️ revisar) |

**Pedidos retenidos** (si `include_holds: true` y hay retenciones):
| Pedido | Retenido desde hace | Estado de preparación |
|--------|---------------------|-----------------------|
| #XXXX | 3 días | ON_HOLD |

## Manejo de errores
| Error | Causa | Solución |
|-------|-------|----------|
| No llega ningún pedido | No hay pedidos abiertos | Todo está despachado: no hace falta actuar |
| `fulfillmentOrders` llega vacío | El pedido todavía no tiene asignaciones de preparación | Puede que el pedido no se haya asignado a una ubicación |
| Límite de solicitudes (429) | Mucho volumen de pedidos con paginación | Baja `limit` a 100 |

## Buenas prácticas
1. Corre este resumen a primera hora cada mañana, antes de procesar cualquier pedido: te da la cola de excepciones en una sola vista.
2. Los pedidos del tramo de 7 días o más son tu mayor prioridad; investígalos y despáchalos o ponles una retención explícita con un motivo.
3. Usa `format: json` para enviar el resumen a una notificación de Slack o a un script de tablero.
4. Combínala con `shopify-retener-pedidos` para actuar sobre las excepciones que encuentre este resumen sin salir de la CLI.
5. En tiendas con más de 500 pedidos abiertos, usa `limit: 100` y cuenta con que habrá paginación: el resumen igual suma correctamente todas las páginas.
