Saltar al contenido
Chatbots de WhatsApp desde cero
Temario

Ejercicio: Panel del dueño con Google Sheets

  • ⏱ 50 minutos
  • 📶 Nivel: intermedio

Objetivo

Convertir un pedido del bot en una fila de hoja de cálculo, proteger la entrada con un secreto compartido y calcular los números que el dueño quiere ver en su panel. Todo se comprueba con funciones puras.

Cómo se trabaja

La parte A es práctica real con tu cuenta de Google (usa una hoja de prueba, nunca la de un cliente real). La parte B son funciones de JavaScript puro que se comprueban en esta página. Un pedido tiene la forma { id, telefono, items: [{ nombre, cantidad, precio }], total, entrega, direccion, pago, estado, creadoEn }, con creadoEn en milisegundos.

💡 Reto extra

Añade topProductos(filas, n) que lea la columna de productos ("2 x Leche; 1 x Arroz"), sume cantidades por producto entre todas las filas y devuelva los n más vendidos. Es el primer gráfico que le gustaría ver al dueño.

▶ Prueba tu código aquí (opcional)
Consola

Pasos

Marca cada paso a medida que lo completes. Tu avance se guarda en este navegador.

💡 Pista 1: Orden de columnas

Fecha, Pedido, Telefono, Productos, Total, Entrega, Direccion, Pago, Estado: la fila es un arreglo con esos nueve valores en ese orden. items.map(...).join("; ") arma la columna de productos.

💡 Pista 2: Comparar el secreto sin romperse

Envuelve JSON.parse en try/catch. Después comprueba typeof datos.secreto === "string" y compara con ===. Recuerda devolver false si el secreto esperado es una cadena vacía.

💡 Pista 3: Sumar sin errores de decimales

Suma en céntimos: Math.round(total * 100) por fila, y divide entre 100 al final. Así 0.1 + 0.2 no te da 0.30000000000000004.

🔎 Comprueba tu trabajo

Pega tu código y pulsa Comprobar. La revisión ocurre en tu navegador; nada se envía a ningún sitio. Cada punto en rojo incluye una pista. Pega solo el JavaScript, sin las etiquetas <script>.

    ✅ Ver una solución posible

    Intenta resolverlo antes de mirar. Tu versión puede ser distinta y también correcta.

    funciones.js
    function pedidoAFila(p) {
      return [
        new Date(p.creadoEn).toISOString(),
        p.id,
        p.telefono,
        p.items.map((i) => `${i.cantidad} x ${i.nombre}`).join("; "),
        p.total,
        p.entrega,
        p.direccion ?? "",
        p.pago,
        p.estado,
      ];
    }
    
    function autorizado(cuerpo, secreto) {
      if (!secreto) return false;
      let datos;
      try { datos = JSON.parse(cuerpo); } catch { return false; }
      return typeof datos?.secreto === "string" && datos.secreto === secreto;
    }
    
    function resumenDelDia(filas, dia) {
      let pedidos = 0;
      let centimos = 0;
      for (const fila of filas) {
        if (!String(fila[0]).startsWith(dia) || fila[8] === "cancelado") continue;
        pedidos++;
        centimos += Math.round(fila[4] * 100);
      }
      return { pedidos, total: centimos / 100 };
    }
    
    function porEstado(filas) {
      const conteo = {};
      for (const fila of filas) conteo[fila[8]] = (conteo[fila[8]] ?? 0) + 1;
      return conteo;
    }