# ACTUALIZACIÓN: CAMPOS DE LAS APIs DE REPORTES

## 🎯 Cambio Realizado

Las funciones de reportes en la API ahora utilizan **las mismas consultas SQL que el módulo CRM**, garantizando consistencia absoluta en los datos.

---

## 📊 ESTRUCTURA DE RESPUESTA DE CADA REPORTE

### **1. Reporte Detallado** (`type=detallado`)

**Endpoint:**
```
GET /api/api.php?action=reports&type=detallado&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

**Respuesta JSON:**
```json
{
  "success": true,
  "type": "detallado",
  "fecha_inicio": "2024-01-01",
  "fecha_fin": "2024-01-31",
  "total_registros": 150,
  "data": [
    {
      "id": 42,
      "wa_message_id": "wamid.HBgNNTkzOTk4MjA1MDUzFQIAERgSMkEzRjRBOEMyNTdEOTc4N0I4AA==",
      "numero": "593998205053",
      "template_name": "bienvenida_cuenta_activa",
      "category": "UTILITY",
      "envio_creado_en": "2024-01-15 10:30:00",
      "delivered_at": "2024-01-15 10:30:02",
      "read_at": "2024-01-15 10:31:30",
      "last_status": "read",
      "last_status_at": "2024-01-15 10:31:30",
      "billable": 1,
      "unit_price": "0.005",
      "currency": "USD",
      "market": "Ecuador",
      "billed_at": "2024-01-15 10:30:05"
    }
  ]
}
```

**Campos devueltos:**
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `id` | int | ID interno del mensaje |
| `wa_message_id` | string | WAMID de WhatsApp |
| `numero` | string | Número E.164 del destinatario |
| `template_name` | string | Nombre de la plantilla utilizada |
| `category` | string | Categoría (UTILITY, MARKETING, etc.) |
| `envio_creado_en` | datetime | Fecha/hora de envío |
| `delivered_at` | datetime | Primera vez que se marcó como entregado |
| `read_at` | datetime | Primera vez que se marcó como leído |
| `last_status` | string | Último estado conocido (sent/delivered/read/failed) |
| `last_status_at` | datetime | Timestamp del último estado |
| `billable` | int | 1 si es cobrable, 0 si no |
| `unit_price` | decimal | Precio unitario del mensaje |
| `currency` | string | Moneda (USD) |
| `market` | string | Mercado (Ecuador, etc.) |
| `billed_at` | datetime | Timestamp de facturación |

---

### **2. Reporte Resumen** (`type=resumen`)

**Endpoint:**
```
GET /api/api.php?action=reports&type=resumen&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

**Respuesta JSON:**
```json
{
  "success": true,
  "type": "resumen",
  "fecha_inicio": "2024-01-01",
  "fecha_fin": "2024-01-31",
  "total_registros": 25,
  "data": [
    {
      "fecha": "2024-01-15",
      "template_name": "bienvenida_cuenta_activa",
      "category": "UTILITY",
      "enviados": 50,
      "entregados": 48,
      "leidos": 45,
      "fallidos": 2,
      "cobrables": 48,
      "costo_total": "0.2400",
      "moneda": "USD"
    }
  ]
}
```

**Campos devueltos:**
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `fecha` | date | Fecha agrupada |
| `template_name` | string | Nombre de la plantilla |
| `category` | string | Categoría del mensaje |
| `enviados` | int | Total de mensajes enviados |
| `entregados` | int | Total con último estado = delivered |
| `leidos` | int | Total con último estado = read |
| `fallidos` | int | Total con último estado = failed |
| `cobrables` | int | Total de mensajes billable = 1 |
| `costo_total` | decimal | Suma de unit_price (4 decimales) |
| `moneda` | string | Moneda (USD) |

---

### **3. Reporte de Errores** (`type=errores`)

**Endpoint:**
```
GET /api/api.php?action=reports&type=errores&token=token-prototipo-123
```

**Respuesta JSON:**
```json
{
  "success": true,
  "type": "errores",
  "fecha_inicio": "",
  "fecha_fin": "",
  "total_registros": 62,
  "data": {
    "errores": [
      {
        "error_code": "131049",
        "error_title": "This message was not delivered to maintain healthy ecosystem engagement.",
        "ocurrencias": 25
      }
    ],
    "numeros_fallidos": [
      {
        "to_e164": "593912345678",
        "ocurrencias": 10
      }
    ]
  }
}
```

**Estructura de respuesta:**
```json
{
  "errores": [
    {
      "error_code": "string",
      "error_title": "string",
      "ocurrencias": int
    }
  ],
  "numeros_fallidos": [
    {
      "to_e164": "string",
      "ocurrencias": int
    }
  ]
}
```

**Campos devueltos en `errores`:**
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `error_code` | string | Código de error de WhatsApp |
| `error_title` | string | Descripción del error |
| `ocurrencias` | int | Cantidad de veces que ocurrió |

**Campos devueltos en `numeros_fallidos`:**
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `to_e164` | string | Número con fallos |
| `ocurrencias` | int | Cantidad de fallos |

**Límite:** Por defecto retorna top 50 de cada categoría.

---

### **4. Reporte de Conversaciones** (`type=conversaciones`)

**Endpoint:**
```
GET /api/api.php?action=reports&type=conversaciones&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

**Respuesta JSON:**
```json
{
  "success": true,
  "type": "conversaciones",
  "fecha_inicio": "2024-01-01",
  "fecha_fin": "2024-01-31",
  "total_registros": 85,
  "data": [
    {
      "phone_number": "593998205053",
      "mensajes_enviados": 3,
      "respuestas_recibidas": 5,
      "primera_interaccion": "2024-01-15 10:30:00",
      "ultima_interaccion": "2024-01-20 14:25:00",
      "total_interacciones": 8
    }
  ]
}
```

**Campos devueltos:**
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `phone_number` | string | Número del contacto |
| `mensajes_enviados` | int | Count DISTINCT de messages.id |
| `respuestas_recibidas` | int | Count DISTINCT de incoming_messages.id |
| `primera_interaccion` | datetime | MIN(sent_at) |
| `ultima_interaccion` | datetime | MAX entre sent_at e incoming timestamp |
| `total_interacciones` | int | Suma de enviados + recibidos (calculado) |

**Nota:** Requiere tabla `incoming_messages` con campos:
- `from_number` (join con messages.to_e164)
- `timestamp` (UNIX timestamp)

---

### **5. Reporte de Mensajes Entrantes** (`type=entrantes`)

**Endpoint:**
```
GET /api/api.php?action=reports&type=entrantes&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

**Respuesta JSON:**
```json
{
  "success": true,
  "type": "entrantes",
  "fecha_inicio": "2024-01-01",
  "fecha_fin": "2024-01-31",
  "total_registros": 120,
  "data": [
    {
      "id": 458,
      "wa_message_id": "wamid.HBgNNTkzOTk4MjA1MDUzFQIAEhggNkNBNjI2NzEyMTQ4QzM4QjI3AA==",
      "numero_cliente": "593998205053",
      "nombre_cliente": "Juan Pérez",
      "tipo_mensaje": "text",
      "contenido": "Hola, necesito ayuda con mi cuenta",
      "fecha_hora": "2024-01-15 10:35:00",
      "es_respuesta": "SI",
      "responde_a_plantilla": "bienvenida_cuenta_activa",
      "mensaje_enviado_el": "2024-01-15 10:30:00",
      "media_id": "",
      "media_mime_type": "",
      "recibido_sistema": "2024-01-15 10:35:01"
    }
  ]
}
```

**Campos devueltos:**
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `id` | int | ID del mensaje entrante |
| `wa_message_id` | string | WAMID del mensaje recibido |
| `numero_cliente` | string | Número que envió el mensaje |
| `nombre_cliente` | string | Nombre del perfil (IFNULL = '') |
| `tipo_mensaje` | string | text, image, audio, video, document, etc. |
| `contenido` | string | Cuerpo del mensaje (IFNULL = '') |
| `fecha_hora` | string | Timestamp formateado (FROM_UNIXTIME) |
| `es_respuesta` | string | 'SI' o 'NO' (IF is_reply = 1) |
| `responde_a_plantilla` | string | Template al que responde (IFNULL = '') |
| `mensaje_enviado_el` | string | Fecha del mensaje outgoing relacionado |
| `media_id` | string | ID del media si aplica (IFNULL = '') |
| `media_mime_type` | string | Tipo MIME del media (IFNULL = '') |
| `recibido_sistema` | datetime | Timestamp de recepción en el sistema |

**Nota:** Requiere tabla `incoming_messages` con campos:
- `wa_message_id`
- `from_number`
- `profile_name`
- `message_type`
- `message_body`
- `timestamp` (UNIX)
- `is_reply`
- `related_outgoing_message_id` (FK a messages.id)
- `media_id`
- `media_mime_type`
- `received_at`

---

## 🔗 Relaciones entre Tablas

### Esquema utilizado:
```
messages
├── id (PK)
├── wa_message_id
├── to_e164
├── template_name
├── category
└── sent_at

message_status
├── message_id (FK → messages.id)
├── status (sent/delivered/read/failed)
├── ts
├── error_code
└── error_title

billing_events
├── message_id (FK → messages.id)
├── billable (0 o 1)
├── unit_price
├── currency
├── market
└── ts

incoming_messages
├── id (PK)
├── wa_message_id
├── from_number
├── profile_name
├── message_type
├── message_body
├── timestamp (UNIX)
├── is_reply
├── related_outgoing_message_id (FK → messages.id)
├── media_id
├── media_mime_type
└── received_at
```

---

## ✅ Compatibilidad con CRM

Todas las funciones de reporte **devuelven exactamente los mismos campos** que las funciones de exportación Excel del CRM:

| Función API | Función CRM Equivalente | Archivo |
|-------------|------------------------|---------|
| `getReporteDetallado()` | `exportDetailedReport()` | functions.php:1289 |
| `getReporteResumen()` | `exportSummaryReport()` | functions.php:1374 |
| `getReporteErrores()` | `exportErrorsReport()` + helpers | functions.php:1453 |
| `getReporteConversaciones()` | `exportConversationsReport()` | functions.php:1521 |
| `getReporteMensajesEntrantes()` | `exportIncomingMessagesReport()` | functions.php:1599 |

---

## 📝 Notas de Implementación Node.js

### Ejemplo de consumo:

```javascript
// 1. Reporte Detallado
const response = await axios.get('https://apiwhats.artechsolutions-ec.com/api/api.php', {
  params: {
    action: 'reports',
    type: 'detallado',
    from: '2024-01-01',
    to: '2024-01-31',
    token: 'token-prototipo-123'
  }
});

const detailData = response.data.data; // Array de objetos con 15 campos

// 2. Procesar para Excel
detailData.forEach(row => {
  worksheet.addRow([
    row.id,
    row.wa_message_id,
    row.numero,
    row.template_name,
    row.category,
    row.envio_creado_en,
    row.delivered_at,
    row.read_at,
    row.last_status,
    row.last_status_at,
    row.billable,
    row.unit_price,
    row.currency,
    row.market,
    row.billed_at
  ]);
});
```

### Validación de campos NULL

Algunos campos pueden ser NULL dependiendo del estado del mensaje:
- `delivered_at`: NULL si nunca fue entregado
- `read_at`: NULL si nunca fue leído
- `unit_price`, `currency`, `market`, `billed_at`: NULL si no hay billing_event

**Recomendación:** Usar IFNULL o validar en Node.js antes de escribir a Excel.

---

## 🔄 Próximos Pasos

1. **Actualizar documentación principal** (DOCUMENTACION_API_PARA_NODE.md) con estos campos exactos
2. **Probar cada endpoint** con Postman/Insomnia
3. **Generar código Node.js** con los nombres de campos correctos
4. **Validar que Excel generado tenga las mismas columnas** que el CRM

---

## 📞 Contacto

Si encuentras discrepancias entre los campos de la API y el CRM, verifica:
1. Que `crm/includes/reports_functions.php` esté actualizado
2. Que `api/api.php` esté llamando correctamente con `['date_from' => ..., 'date_to' => ...]`
3. Que las funciones helper (`getTopErrors`, `getTopFailedNumbers`) estén disponibles
