# 🚀 GUÍA RÁPIDA: CONSUMIR APIS DE REPORTES DESDE NODE.JS

## 📌 Resumen Ejecutivo

Las APIs de reportes ahora **devuelven exactamente los mismos campos que el CRM** de WhatsApp. No hay transformaciones, cálculos ni estructuras diferentes. Lo que ves en el Excel del CRM es lo mismo que devuelve la API.

---

## 🎯 5 Endpoints Disponibles

| Tipo | Requiere Fechas | Descripción |
|------|----------------|-------------|
| `detallado` | ✅ Sí | Cada mensaje con timestamps, estados y costos |
| `resumen` | ✅ Sí | Agrupado por fecha/plantilla/categoría |
| `errores` | ❌ No | Top errores y números problemáticos (histórico) |
| `conversaciones` | ✅ Sí | Mensajes enviados + respuestas recibidas por número |
| `entrantes` | ✅ Sí | Solo mensajes recibidos de clientes |

---

## 📋 ENDPOINT 1: Reporte Detallado

### Request:
```http
GET https://apiwhats.artechsolutions-ec.com/api/api.php?action=reports&type=detallado&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

### Response:
```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.ABC123...",
      "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"
    }
  ]
}
```

### Node.js Code:
```javascript
const axios = require('axios');
const ExcelJS = require('exceljs');

async function generateDetailedReport(from, to) {
  // 1. Obtener datos de la API
  const response = await axios.get('https://apiwhats.artechsolutions-ec.com/api/api.php', {
    params: {
      action: 'reports',
      type: 'detallado',
      from,
      to,
      token: 'token-prototipo-123'
    }
  });

  const data = response.data.data;

  // 2. Crear Excel
  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('Reporte Detallado');

  // 3. Headers
  worksheet.columns = [
    { header: 'ID', key: 'id', width: 10 },
    { header: 'WhatsApp Message ID', key: 'wa_message_id', width: 40 },
    { header: 'Numero', key: 'numero', width: 15 },
    { header: 'Plantilla', key: 'template_name', width: 25 },
    { header: 'Categoria', key: 'category', width: 12 },
    { header: 'Envio Creado', key: 'envio_creado_en', width: 20 },
    { header: 'Entregado En', key: 'delivered_at', width: 20 },
    { header: 'Leido En', key: 'read_at', width: 20 },
    { header: 'Ultimo Estado', key: 'last_status', width: 15 },
    { header: 'Ultimo Estado En', key: 'last_status_at', width: 20 },
    { header: 'Cobrable', key: 'billable', width: 10 },
    { header: 'Precio Unitario', key: 'unit_price', width: 15 },
    { header: 'Moneda', key: 'currency', width: 10 },
    { header: 'Mercado', key: 'market', width: 15 },
    { header: 'Facturado En', key: 'billed_at', width: 20 }
  ];

  // 4. Estilo del header
  worksheet.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
  worksheet.getRow(1).fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FF3498db' }
  };
  worksheet.getRow(1).alignment = { horizontal: 'center' };

  // 5. Agregar datos
  data.forEach(row => {
    worksheet.addRow(row);
  });

  // 6. Guardar archivo
  await workbook.xlsx.writeFile(`reporte_detallado_${from}_to_${to}.xlsx`);
  console.log('✅ Reporte generado');
}

// Uso
generateDetailedReport('2024-01-01', '2024-01-31');
```

---

## 📋 ENDPOINT 2: Reporte Resumen

### Request:
```http
GET https://apiwhats.artechsolutions-ec.com/api/api.php?action=reports&type=resumen&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

### Response:
```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"
    }
  ]
}
```

### Node.js Code:
```javascript
async function generateSummaryReport(from, to) {
  const response = await axios.get('https://apiwhats.artechsolutions-ec.com/api/api.php', {
    params: {
      action: 'reports',
      type: 'resumen',
      from,
      to,
      token: 'token-prototipo-123'
    }
  });

  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('Reporte Resumen');

  worksheet.columns = [
    { header: 'Fecha', key: 'fecha', width: 12 },
    { header: 'Plantilla', key: 'template_name', width: 25 },
    { header: 'Categoria', key: 'category', width: 12 },
    { header: 'Enviados', key: 'enviados', width: 10 },
    { header: 'Entregados', key: 'entregados', width: 12 },
    { header: 'Leidos', key: 'leidos', width: 10 },
    { header: 'Fallidos', key: 'fallidos', width: 10 },
    { header: 'Cobrables', key: 'cobrables', width: 12 },
    { header: 'Costo Total', key: 'costo_total', width: 12 },
    { header: 'Moneda', key: 'moneda', width: 10 }
  ];

  worksheet.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
  worksheet.getRow(1).fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FF27ae60' }
  };

  response.data.data.forEach(row => worksheet.addRow(row));

  await workbook.xlsx.writeFile(`reporte_resumen_${from}_to_${to}.xlsx`);
}
```

---

## 📋 ENDPOINT 3: Reporte de Errores

### Request:
```http
GET https://apiwhats.artechsolutions-ec.com/api/api.php?action=reports&type=errores&token=token-prototipo-123
```

### Response:
```json
{
  "success": true,
  "type": "errores",
  "total_registros": 62,
  "data": {
    "errores": [
      {
        "error_code": "131049",
        "error_title": "This message was not delivered...",
        "ocurrencias": 25
      }
    ],
    "numeros_fallidos": [
      {
        "to_e164": "593912345678",
        "ocurrencias": 10
      }
    ]
  }
}
```

### Node.js Code:
```javascript
async function generateErrorsReport() {
  const response = await axios.get('https://apiwhats.artechsolutions-ec.com/api/api.php', {
    params: {
      action: 'reports',
      type: 'errores',
      token: 'token-prototipo-123'
    }
  });

  const workbook = new ExcelJS.Workbook();
  
  // Hoja 1: Errores
  const sheet1 = workbook.addWorksheet('Top Errores');
  sheet1.columns = [
    { header: 'Codigo Error', key: 'error_code', width: 12 },
    { header: 'Titulo Error', key: 'error_title', width: 60 },
    { header: 'Ocurrencias', key: 'ocurrencias', width: 12 }
  ];
  
  sheet1.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
  sheet1.getRow(1).fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FFe74c3c' }
  };
  
  response.data.data.errores.forEach(row => sheet1.addRow(row));
  
  // Hoja 2: Números fallidos
  const sheet2 = workbook.addWorksheet('Numeros Fallidos');
  sheet2.columns = [
    { header: 'Numero', key: 'to_e164', width: 20 },
    { header: 'Ocurrencias', key: 'ocurrencias', width: 12 }
  ];
  
  sheet2.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
  sheet2.getRow(1).fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FFe74c3c' }
  };
  
  response.data.data.numeros_fallidos.forEach(row => sheet2.addRow(row));
  
  await workbook.xlsx.writeFile(`reporte_errores_${new Date().toISOString().split('T')[0]}.xlsx`);
}
```

---

## 📋 ENDPOINT 4: Reporte de Conversaciones

### Request:
```http
GET https://apiwhats.artechsolutions-ec.com/api/api.php?action=reports&type=conversaciones&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

### Response:
```json
{
  "success": true,
  "type": "conversaciones",
  "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
    }
  ]
}
```

### Node.js Code:
```javascript
async function generateConversationsReport(from, to) {
  const response = await axios.get('https://apiwhats.artechsolutions-ec.com/api/api.php', {
    params: {
      action: 'reports',
      type: 'conversaciones',
      from,
      to,
      token: 'token-prototipo-123'
    }
  });

  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('Conversaciones');

  worksheet.columns = [
    { header: 'Numero', key: 'phone_number', width: 20 },
    { header: 'Mensajes Enviados', key: 'mensajes_enviados', width: 18 },
    { header: 'Respuestas Recibidas', key: 'respuestas_recibidas', width: 20 },
    { header: 'Total Interacciones', key: 'total_interacciones', width: 18 },
    { header: 'Primera Interaccion', key: 'primera_interaccion', width: 20 },
    { header: 'Ultima Interaccion', key: 'ultima_interaccion', width: 20 }
  ];

  worksheet.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
  worksheet.getRow(1).fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FF9b59b6' }
  };

  response.data.data.forEach(row => worksheet.addRow(row));

  await workbook.xlsx.writeFile(`reporte_conversaciones_${from}_to_${to}.xlsx`);
}
```

---

## 📋 ENDPOINT 5: Mensajes Entrantes

### Request:
```http
GET https://apiwhats.artechsolutions-ec.com/api/api.php?action=reports&type=entrantes&from=2024-01-01&to=2024-01-31&token=token-prototipo-123
```

### Response:
```json
{
  "success": true,
  "type": "entrantes",
  "total_registros": 120,
  "data": [
    {
      "id": 458,
      "wa_message_id": "wamid.ABC123...",
      "numero_cliente": "593998205053",
      "nombre_cliente": "Juan Pérez",
      "tipo_mensaje": "text",
      "contenido": "Hola, necesito ayuda",
      "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"
    }
  ]
}
```

### Node.js Code:
```javascript
async function generateIncomingMessagesReport(from, to) {
  const response = await axios.get('https://apiwhats.artechsolutions-ec.com/api/api.php', {
    params: {
      action: 'reports',
      type: 'entrantes',
      from,
      to,
      token: 'token-prototipo-123'
    }
  });

  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('Mensajes Entrantes');

  worksheet.columns = [
    { header: 'ID', key: 'id', width: 10 },
    { header: 'WhatsApp Message ID', key: 'wa_message_id', width: 40 },
    { header: 'Numero Cliente', key: 'numero_cliente', width: 18 },
    { header: 'Nombre Cliente', key: 'nombre_cliente', width: 25 },
    { header: 'Tipo Mensaje', key: 'tipo_mensaje', width: 15 },
    { header: 'Contenido', key: 'contenido', width: 50 },
    { header: 'Fecha Hora', key: 'fecha_hora', width: 20 },
    { header: 'Es Respuesta', key: 'es_respuesta', width: 12 },
    { header: 'Responde a Plantilla', key: 'responde_a_plantilla', width: 25 },
    { header: 'Mensaje Enviado El', key: 'mensaje_enviado_el', width: 20 },
    { header: 'Media ID', key: 'media_id', width: 30 },
    { header: 'Media Mime Type', key: 'media_mime_type', width: 20 },
    { header: 'Recibido Sistema', key: 'recibido_sistema', width: 20 }
  ];

  worksheet.getRow(1).font = { bold: true, color: { argb: 'FFFFFFFF' } };
  worksheet.getRow(1).fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FFf39c12' }
  };

  response.data.data.forEach(row => worksheet.addRow(row));

  await workbook.xlsx.writeFile(`reporte_mensajes_entrantes_${from}_to_${to}.xlsx`);
}
```

---

## 🛠️ Service Completo Node.js

```javascript
// services/WhatsAppReportService.js
const axios = require('axios');

class WhatsAppReportService {
  constructor() {
    this.baseURL = 'https://apiwhats.artechsolutions-ec.com/api/api.php';
    this.token = 'token-prototipo-123';
  }

  async getReport(type, from = null, to = null) {
    const params = {
      action: 'reports',
      type,
      token: this.token
    };

    if (from) params.from = from;
    if (to) params.to = to;

    try {
      const response = await axios.get(this.baseURL, { params });
      return response.data;
    } catch (error) {
      throw new Error(`Error obteniendo reporte ${type}: ${error.message}`);
    }
  }

  async getDetailedReport(from, to) {
    return this.getReport('detallado', from, to);
  }

  async getSummaryReport(from, to) {
    return this.getReport('resumen', from, to);
  }

  async getErrorsReport() {
    return this.getReport('errores');
  }

  async getConversationsReport(from, to) {
    return this.getReport('conversaciones', from, to);
  }

  async getIncomingMessagesReport(from, to) {
    return this.getReport('entrantes', from, to);
  }
}

module.exports = WhatsAppReportService;
```

### Uso:
```javascript
const WhatsAppReportService = require('./services/WhatsAppReportService');

const service = new WhatsAppReportService();

// Reporte Detallado
const detailed = await service.getDetailedReport('2024-01-01', '2024-01-31');
console.log(`Total mensajes: ${detailed.total_registros}`);

// Reporte de Errores
const errors = await service.getErrorsReport();
console.log(`Top errores: ${errors.data.errores.length}`);
```

---

## ⚠️ Manejo de Errores

```javascript
async function fetchReport(type, from, to) {
  try {
    const response = await axios.get('https://apiwhats.artechsolutions-ec.com/api/api.php', {
      params: { action: 'reports', type, from, to, token: 'token-prototipo-123' }
    });

    if (!response.data.success) {
      throw new Error(response.data.error || 'Error desconocido');
    }

    return response.data;
  } catch (error) {
    if (error.response) {
      // Error HTTP (400, 401, 500, etc.)
      console.error(`HTTP ${error.response.status}: ${error.response.data.error}`);
    } else if (error.request) {
      // No hubo respuesta del servidor
      console.error('No se pudo conectar con la API');
    } else {
      console.error(`Error: ${error.message}`);
    }
    throw error;
  }
}
```

---

## 🎨 Validación de Campos NULL

Algunos campos pueden venir NULL desde la API:

```javascript
function formatRow(row) {
  return {
    ...row,
    delivered_at: row.delivered_at || 'No entregado',
    read_at: row.read_at || 'No leído',
    unit_price: row.unit_price || '0.00',
    currency: row.currency || 'USD',
    market: row.market || 'N/A',
    billed_at: row.billed_at || 'No facturado'
  };
}
```

---

## ✅ Checklist de Implementación

- [ ] Instalar dependencias: `npm install axios exceljs`
- [ ] Crear servicio `WhatsAppReportService.js`
- [ ] Implementar función para cada tipo de reporte
- [ ] Agregar manejo de errores
- [ ] Validar campos NULL antes de escribir a Excel
- [ ] Probar con datos reales del CRM
- [ ] Comparar Excel generado vs Excel del CRM
- [ ] Documentar endpoints en tu README

---

## 📞 Soporte

Si encuentras diferencias entre la API y el CRM, verifica:

1. ✅ Que la tabla `incoming_messages` exista (para reportes 4 y 5)
2. ✅ Que las fechas `from` y `to` estén en formato `YYYY-MM-DD`
3. ✅ Que el token sea correcto: `token-prototipo-123`
4. ✅ Que la URL sea: `https://apiwhats.artechsolutions-ec.com/api/api.php`

---

**Última actualización:** 3 de febrero de 2026  
**Versión:** 1.0  
**Status:** ✅ Listo para implementar
