---
name: shopify-cambios-vs-reembolsos
description: "Solo lectura: mide qué porcentaje de las devoluciones termina en cambio, en reembolso o en crédito en tienda, y calcula cuántos ingresos recuperas. Úsala cuando quieras saber si tu política de devoluciones retiene o pierde ventas."
---

## Propósito
Analiza cómo se resuelven las devoluciones para calcular la proporción entre cambios (ingreso que se conserva), crédito en tienda (ingreso que se aplaza) y reembolsos (ingreso que se pierde). Lo sigue en el tiempo como una métrica de recuperación de ingresos. Solo lectura, sin mutaciones.

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

## Parámetros

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|-------------|----------------|-------------|
| store | string | sí | — | Dominio de la tienda (p. ej., mitienda.myshopify.com) |
| days_back | integer | no | 30 | Ventana de días hacia atrás para las resoluciones de devoluciones |
| compare_days_back | integer | no | 0 | Periodo anterior opcional para comparar (0 = sin comparación) |
| format | string | no | human | Formato de salida: `human` o `json` |

## Seguridad

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

## Pasos

1. **OPERACIÓN:** `returns` — consulta
   **Entradas:** `query: "created_at:>='<NOW - days_back days>'"`, `first: 250`, cursor de paginación
   **Resultado esperado:** Devoluciones con `refunds { totalRefundedSet }`, `exchangeLineItems` y estado de resolución

2. Clasifica cómo se resolvió cada devolución:
   - **Cambio**: la devolución tiene `exchangeLineItems` con cantidad > 0
   - **Crédito en tienda**: la devolución tiene `refunds` pagados con tarjeta de regalo o crédito en tienda
   - **Reembolso**: la devolución tiene un reembolso en efectivo o a la tarjeta, sin cambio

3. **OPERACIÓN:** `orders` — consulta (si `compare_days_back > 0`)
   **Entradas:** La misma lógica para el periodo anterior, para calcular la tendencia

## Operaciones GraphQL

```graphql
# returns:query — validada con api_version 2025-01
query ReturnResolutions($query: String!, $after: String) {
  returns(first: 250, after: $after, query: $query) {
    edges {
      node {
        id
        status
        createdAt
        totalQuantity
        order {
          id
          name
        }
        exchangeLineItems(first: 10) {
          edges {
            node {
              id
              quantity
              lineItem {
                variant {
                  id
                  title
                }
              }
            }
          }
        }
        refunds(first: 5) {
          id
          totalRefundedSet {
            shopMoney {
              amount
              currencyCode
            }
          }
        }
        returnLineItems(first: 20) {
          edges {
            node {
              refundableQuantity
              returnReason
            }
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

```graphql
# orders:query — validada con api_version 2025-01
query OrdersInPeriod($query: String!, $after: String) {
  orders(first: 250, after: $after, query: $query) {
    edges {
      node {
        id
        name
        totalPriceSet {
          shopMoney {
            amount
            currencyCode
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

## Seguimiento de la sesión

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

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

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

**Al terminar**, muestra:

Para `format: human` (predeterminado):
```
══════════════════════════════════════════════
CAMBIOS VS. REEMBOLSOS  (<days_back> días)
  Devoluciones resueltas:  <n>

  Desglose por resolución:
    Cambio (ingreso conservado):     <n>  (<pct>%)
    Crédito en tienda (aplazado):    <n>  (<pct>%)
    Reembolso (ingreso perdido):     <n>  (<pct>%)

  Tasa de recuperación de ingresos: <pct>%
  (cambios + crédito en tienda como % de todas las devoluciones)

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

Para `format: json`, muestra:
```json
{
  "skill": "shopify-cambios-vs-reembolsos",
  "store": "<dominio>",
  "period_days": 30,
  "total_returns": 0,
  "exchanges": { "count": 0, "pct": 0 },
  "store_credit": { "count": 0, "pct": 0 },
  "refunds": { "count": 0, "pct": 0 },
  "revenue_recovery_rate_pct": 0,
  "output_file": "exchange_refund_ratio_<fecha>.csv"
}
```

## Formato de salida
Archivo CSV `exchange_refund_ratio_<AAAA-MM-DD>.csv` con las columnas:
`return_id`, `order_name`, `resolution_type`, `exchange_sku`, `refund_amount`, `currency`, `created_at`

## 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 |
| No hay devoluciones resueltas en la ventana | No se completaron devoluciones en el periodo | Termina con el resumen: 0 devoluciones |
| Sin artículos de cambio aunque el estado indica cambio | Cambio todavía en curso | Cuéntalo como pendiente y exclúyelo de la proporción |

## Buenas prácticas
- Una tasa de recuperación de ingresos superior al 30 % (cambios + crédito en tienda) suele ser una buena señal en moda y ropa; define tu propia referencia según tu categoría.
- Usa `compare_days_back` para ver si los cambios en tu política de devoluciones (p. ej., periodos de «solo cambios») mejoraron la tasa de recuperación.
- Combínala con `shopify-motivos-devolucion`: muchas devoluciones por «talla equivocada» junto con pocos cambios pueden indicar problemas en la guía de tallas de tus fichas de producto.
- Ejecútala antes y después de lanzar un incentivo para cambios (p. ej., crédito extra en tienda por cambiar en lugar de pedir reembolso) para medir el impacto.
