Saltar al contenido
Chatbots de WhatsApp desde cero
Temario

Ejercicio: Costos y métricas de tu bot

  • ⏱ 45 minutos
  • 📶 Nivel: intermedio

Objetivo

Construir una calculadora de costos con tarifas parametrizables y las funciones que resumen las métricas del bot, para poder presentarle al dueño del minimarket cuánto cuesta y qué resultados da.

Cómo se trabaja

La parte A es de investigación con la documentación oficial. La parte B son tres funciones de JavaScript puro. Las tarifas del ejercicio son de ejemplo, no las de Meta.

Un mensaje del mes se describe así: { categoria: "marketing" | "utilidad" | "autenticacion" | "servicio", cantidad: 80, enPuntoDeEntrada: true | false }. Las tarifas son un objeto como { marketing: 0.06, utilidad: 0.02, autenticacion: 0.02, servicio: 0.01, servicioGratis: 1000 }. Una conversación es { estado: "resuelta" | "derivada" | "abandonada" }.

💡 Reto extra

Añade costoPorPedido(costoMeta, costoInfra, pedidos) que devuelva cuánto cuesta cada pedido recibido por el bot (0 si no hubo pedidos). Es la cifra que más le gusta ver a un dueño: «cada pedido por WhatsApp me cuesta S/ 0.20».

▶ 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: Cobrar o no cobrar

Calcula el precio de cada mensaje con tarifas[m.categoria] ?? 0 y salta los mensajes enPuntoDeEntrada y, para servicio, guarda en una variable cuántos mensajes gratis quedan y réstala entrada tras entrada.

💡 Pista 2: Redondear

Math.round(x * 100) / 100 redondea a 2 decimales y Math.round(x * 1000) / 1000 a 3. Los errores de coma flotante son normales; el redondeo final los arregla.

💡 Pista 3: Contar eventos

Una función auxiliar n = tipo => eventos.filter(e => e.tipo === tipo).length evita repetir código. Para el tiempo medio, filtra los eventos respuesta y promedia su ms.

🔎 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.

    costos.js
    function costoMensual(mensajes, tarifas) {
      let total = 0;
      let gratisServicio = tarifas.servicioGratis ?? 0;
      for (const m of mensajes) {
        if (m.enPuntoDeEntrada) continue;
        let cobrables = m.cantidad;
        if (m.categoria === "servicio") {
          cobrables = Math.max(0, m.cantidad - gratisServicio);
          gratisServicio = Math.max(0, gratisServicio - m.cantidad);
        }
        total += (tarifas[m.categoria] ?? 0) * cobrables;
      }
      return Math.round(total * 100) / 100;
    }
    
    function tasaDeResolucion(conversaciones) {
      if (conversaciones.length === 0) return 0;
      const resueltas = conversaciones.filter(c => c.estado === "resuelta").length;
      return Math.round((resueltas / conversaciones.length) * 1000) / 1000;
    }
    
    function resumenMetricas(eventos) {
      const n = tipo => eventos.filter(e => e.tipo === tipo).length;
      const resp = eventos.filter(e => e.tipo === "respuesta");
      const conversaciones = n("conversacion_iniciada");
      const enviadas = n("plantilla_enviada");
      const redondear = (x, d) => Math.round(x * 10 ** d) / 10 ** d;
      return {
        conversaciones,
        tasaResolucion: conversaciones ? redondear(n("conversacion_resuelta") / conversaciones, 3) : 0,
        pedidosPorConversacion: conversaciones ? redondear(n("pedido") / conversaciones, 3) : 0,
        tiempoRespuestaMedioMs: resp.length ? Math.round(resp.reduce((s, e) => s + e.ms, 0) / resp.length) : 0,
        tasaLectura: enviadas ? redondear(n("plantilla_leida") / enviadas, 3) : 0,
        bajas: n("baja"),
      };
    }