---
name: shopify-historial-cliente
description: "Exporta en un solo CSV la historia completa de un cliente en orden cronológico: pedidos, reembolsos, devoluciones, direcciones, notas, etiquetas, consentimiento de marketing y gasto total. Úsala ante un caso escalado, una solicitud de datos o antes de unir o borrar una cuenta."
---

## Propósito
Genera un expediente completo y cronológico de un solo cliente. Trae la ficha del cliente (identidad, consentimiento de marketing, totales históricos, etiquetas, notas, direcciones) y todos los pedidos que ha hecho (con sus artículos, despachos, reembolsos y devoluciones), y entrega un CSV unificado más una línea de tiempo fácil de leer. Lo usan los agentes de soporte que atienden casos escalados, sirve para responder solicitudes de exportación de datos y funciona como copia fiel de la información antes de unir o eliminar una cuenta. Solo lectura: no ejecuta mutaciones.

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

## Parámetros

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|-------------|----------------|-------------|
| store | string | sí | — | Dominio de la tienda (p. ej., tu-tienda.myshopify.com) |
| format | string | no | human | Formato de salida: `human` o `json` |
| customer_id | string | sí | — | GID del cliente (p. ej., `gid://shopify/Customer/12345`) |
| include_line_items | bool | no | true | Incluye en el CSV una fila por cada artículo del pedido |
| include_refunds | bool | no | true | Incluye los reembolsos y las devoluciones como filas separadas en la línea de tiempo |
| max_orders | integer | no | 250 | Tope de pedidos a traer (primero los más recientes); 0 = sin tope |

## Seguridad

> ℹ️ Skill de solo lectura: no ejecuta mutaciones. Puedes ejecutarla en cualquier momento sin riesgo. El resultado contiene datos personales que identifican al cliente: maneja el CSV con el mismo cuidado que cualquier exportación de clientes y bórralo cuando se cierre el caso de soporte.

## Pasos

1. **OPERACIÓN:** `customer` — consulta
   **Entradas:** `id: <customer_id>`; selecciona los campos de identidad, los totales históricos, las etiquetas, la nota, el consentimiento de marketing, las direcciones y createdAt
   **Resultado esperado:** El encabezado con los datos del cliente; si la respuesta es `null`, detente con un error claro

2. **OPERACIÓN:** `orders` — consulta
   **Entradas:** `query: "customer_id:<numeric_id>"`, `first: 250`, `sortKey: CREATED_AT`, `reverse: true`, selecciona `id`, `name`, `createdAt`, `processedAt`, `displayFinancialStatus`, `displayFulfillmentStatus`, `totalPriceSet`, `totalShippingPriceSet`, `totalDiscountsSet`, `lineItems(first: 50) { node { id title quantity sku discountedTotalSet variant { sku } } }`, `fulfillments { id status deliveredAt trackingInfo { number url } }`, `refunds { id createdAt totalRefundedSet refundLineItems(first: 50) { node { lineItem { id title } quantity subtotalSet } } }` y el cursor de paginación (detente en `max_orders` si está definido)
   **Resultado esperado:** La lista cronológica completa de pedidos con sus reembolsos y despachos

3. Arma los eventos de la línea de tiempo unificada: creación del cliente → cada pedido → cada reembolso o devolución de cada pedido. Ordena todos los eventos por fecha y hora de forma ascendente para el resumen legible; el CSV también va en orden ascendente.

## Operaciones GraphQL

```graphql
# customer:query — validado con api_version 2025-01
query CustomerHeaderForTimeline($id: ID!) {
  customer(id: $id) {
    id
    displayName
    firstName
    lastName
    defaultEmailAddress { emailAddress }
    phone
    note
    tags
    numberOfOrders
    amountSpent { amount currencyCode }
    emailMarketingConsent { marketingState marketingOptInLevel consentUpdatedAt }
    smsMarketingConsent { marketingState marketingOptInLevel consentUpdatedAt }
    addresses(first: 25) {
      id firstName lastName address1 address2 city provinceCode countryCodeV2 zip phone
    }
    defaultAddress { id }
    createdAt
    updatedAt
  }
}
```

```graphql
# orders:query — validado con api_version 2025-01
query CustomerOrdersForTimeline($query: String!, $after: String) {
  orders(first: 250, after: $after, query: $query, sortKey: CREATED_AT, reverse: true) {
    edges {
      node {
        id
        name
        createdAt
        processedAt
        displayFinancialStatus
        displayFulfillmentStatus
        cancelledAt
        cancelReason
        totalPriceSet { shopMoney { amount currencyCode } }
        totalShippingPriceSet { shopMoney { amount currencyCode } }
        totalDiscountsSet { shopMoney { amount currencyCode } }
        lineItems(first: 50) {
          edges { node {
            id title quantity sku
            discountedTotalSet { shopMoney { amount currencyCode } }
            variant { id sku }
          } }
        }
        fulfillments {
          id status deliveredAt
          trackingInfo { number url company }
        }
        refunds {
          id
          createdAt
          totalRefundedSet { shopMoney { amount currencyCode } }
          refundLineItems(first: 50) {
            edges { node {
              quantity
              lineItem { id title }
              subtotalSet { 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: Historial completo de un cliente     ║
║  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):
```
══════════════════════════════════════════════
HISTORIAL DEL CLIENTE
  Cliente:          <nombre> (<correo>)  ID: <customer_id>
  Cliente desde:    <createdAt>
  Gasto total:      <monto> <moneda>   Pedidos totales: <n>   Total reembolsado: <monto>
  Etiquetas:        <lista>
  Consentimiento por correo: <estado> (desde <fecha>)   Consentimiento por SMS: <estado> (desde <fecha>)

  Línea de tiempo reciente (lo más reciente primero):
    <fecha>  PEDIDO      <name>  <monto>  <estado de pago> / <estado de despacho>
    <fecha>  REEMBOLSO   <id>    <monto>
    <fecha>  DEVOLUCIÓN  <id>    artículos: <n>
    ...
  Archivo: customer_timeline_<customer_id>_<fecha>.csv
══════════════════════════════════════════════
```

Para `format: json`, muestra:
```json
{
  "skill": "shopify-historial-cliente",
  "store": "<dominio>",
  "customer_id": "<gid>",
  "header": {
    "name": "<texto>", "email": "<texto>", "phone": "<texto>",
    "joined": "<ISO8601>", "lifetime_spend": 0, "currency": "USD",
    "total_orders": 0, "tags": [],
    "email_consent": "<estado>", "sms_consent": "<estado>"
  },
  "totals": { "orders": 0, "refunds_count": 0, "refunds_amount": 0 },
  "output_file": "customer_timeline_<customer_id>_<fecha>.csv"
}
```

## Formato de salida
Archivo CSV `customer_timeline_<customer_id>_<AAAA-MM-DD>.csv` con las columnas:
`event_datetime`, `event_type`, `event_id`, `order_name`, `line_item_title`, `sku`, `quantity`, `amount`, `currency`, `financial_status`, `fulfillment_status`, `tracking_number`, `notes`

Los tipos de evento incluyen: `customer_created`, `order_placed`, `order_fulfilled`, `order_delivered`, `order_cancelled`, `refund_issued`, `return_initiated`.

## 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 |
| Cliente no encontrado | GID equivocado | Usa `shopify-buscar-pedido` para encontrar un pedido reciente y luego lee `customer.id` |
| 0 pedidos | Cuenta nueva o compras solo como invitado | Entrega una línea de tiempo solo con el encabezado |
| Pedido anonimizado | Borrado de datos por GDPR | Omite los artículos y agrega una fila de marcador |
| Paginación más allá de `max_orders` | Se alcanzó el tope | Detente y marca `truncated: true` |

## Buenas prácticas
- Ejecútala antes de cualquier unión, eliminación o escalamiento: una vez que se confirma una unión, el estado anterior no se puede reconstruir.
- Para clientes con muchos pedidos usa `max_orders: 50`; casi nunca se necesita toda la historia para un caso de soporte.
- El CSV está ordenado por evento, así que puedes armar tablas dinámicas sin reorganizar los datos.
- Úsala junto con `shopify-unir-clientes`: ejecútala sobre la cuenta que se conserva y sobre la que se elimina antes de unirlas, para tener un registro permanente previo a la unión.
