Saltar a contenido

SDD — Bot Rinde · Soporte de cuenta

Ficha técnica

Campo Valor
Repositorio / carpeta salesiq/bot-rinde/
Plataforma Zoho SalesIQ · Zobot con código Deluge
Disparo Mensaje entrante por WhatsApp
Código flujos/message_handler.dg (9 líneas) · flujos/context_handler.dg (729 líneas) · flujos/error_handler.dg (3 líneas)
Integraciones Rinde Plus Admin API, SalesIQ REST API, Zoho AI (OCR)
Proceso de negocio PDD

1. Arquitectura general

flowchart LR
    WA[WhatsApp] --> SIQ[Zoho SalesIQ<br/>Zobot Deluge]
    SIQ -->|login-sin-captcha · verificar-dpi<br/>desbloquear · cambiar-celular| RP[Rinde Plus Admin API]
    SIQ -->|recognizeText| OCR[Zoho AI OCR]
    SIQ -->|PUT conversations/tags<br/>conexión salesiq_conn| TAG[SalesIQ REST API]
    SIQ -->|forward| AG[Agentes SalesIQ]

La lógica vive en los tres handlers y se ejecuta en Zoho en cada mensaje. El bot no guarda datos propios: todo el estado que debe pasar de un contexto a otro viaja en el nombre del context_id.

2. Componentes

Handler Responsabilidad
message_handler Punto de entrada: saludo, menú de trámites y contexto menu_principal
context_handler Validación de identidad, trámites, reintentos, cierre y etiquetado
error_handler Ante una excepción no controlada responde "inconveniente técnico" y hace forward

Contextos del context_handler (el propio código trae este mapa en el encabezado):

context_id Líneas Espera Qué hace
menu_principal 45–68 opcion Decide op y abre validar_<op>_1
validar_<op>_<n> 70–443 dpi, nombre, apellido, foto Validación de identidad y, si es activar, el desbloqueo
reintento_<op>_<n> 445–502 decision Reintentar, agente o menú tras fallar la validación
cambio_numero_<n>_<dpi> 504–613 telefono Pide el número y llama a cambiar-celular
cambio_reintento_<n>_<dpi> 615–668 decision Reintentar el número, agente o menú
fin 670–697 cierre Menú, agente o finalizar
cualquier otro 699–707 — Vuelve a menu_principal
(todos) 709–728 — Envía la etiqueta pendiente del turno

op es activar o telefono. n es el intento, de 1 a 3, siempre un dígito.

3. Flujo detallado

3.1 Reglas de diseño del código

El encabezado del context_handler documenta dos reglas que hay que respetar al editar:

  • answers se limpia al cambiar de context_id. Lo que deba sobrevivir (operación, intento, DPI) va en el nombre del contexto.
  • Un contexto emite la pregunta y el siguiente la procesa, nunca las dos cosas en el mismo turno.

El despachador usa startsWith, así que los prefijos deben ser excluyentes. Por eso el reintento del número se llama cambio_reintento_ y no reintento_numero_.

3.2 Validación de identidad (validar_<op>_<n>)

Pregunta un dato por turno, en este orden:

  1. dpi. Se limpian los no dígitos y se valida el CUI: 13 dígitos, módulo 11 de los 8 primeros con pesos 2 a 9 igual al noveno, departamento 01–22 y municipio ≥ 01. Si no pasa, se elimina la respuesta y se vuelve a preguntar sin llamar a la API.
  2. Login y POST /auth/usuarios/verificar-dpi. Si existe ≠ 1, pasa a reintento_<op>_<n>. Si existe, pregunta nombre.
  3. apellido.
  4. foto: un archivo jpg, jpeg o png.
  5. Con la foto:
    1. Nuevo login y nueva consulta a verificar-dpi para obtener los nombres registrados (no hay dónde guardarlos entre turnos).
    2. OCR con zoho.ai.recognizeText(archivo) con el modelo por defecto.
    3. Del texto se quedan solo los dígitos, se separan en grupos y se prueban ventanas consecutivas hasta 13 dígitos. La primera que pasa el dígito verificador es cui_foto.
    4. Se normalizan nombre y apellido a mayúsculas sin acentos ni Ñ y se buscan dentro de los nombres y apellidos registrados.
  6. Decisión:
Resultado Siguiente
cui_foto vacío Pide la foto otra vez, sin consumir intento
existe ≠ 1, DPI distinto o nombre no coincide reintento_<op>_<n>
Válido y op = telefono cambio_numero_1_<dpi>
Válido y op = activar POST /auth/usuarios/desbloquear y fin o reintento_activar_<n>

3.3 Activación

desbloquear con el DPI. ok = true es éxito; si además trae message, la cuenta ya estaba activa. Cualquier otra respuesta (403, 404, 409) va a reintento_activar_<n>.

3.4 Cambio de número (cambio_numero_<n>_<dpi>)

  1. El DPI se toma del nombre del contexto (todo lo que va después de <n>_).
  2. Pide telefono, deja solo dígitos y exige 8.
  3. Login y POST /auth/usuarios/cambiar-celular con dpi y nuevoTelefono.
  4. ok = true es éxito; con message, el número ya era el registrado. Un fallo (409 número de otro usuario o DPI duplicado, 404, 400) va a cambio_reintento_<n>_<dpi>, que solo vuelve a pedir el número.

3.5 Reintentos

Los dos contextos de reintento leen el intento del nombre. "Reintentar" con n < 3 abre el siguiente intento; con n = 3 responde "Ya no es posible reintentar" y ofrece solo agente o menú. "Contactar con agente" hace forward. "Ir al menú principal" vuelve a menu_principal.

3.6 Etiquetado

El punto de decisión asigna tag_pendiente. Al final del turno, si hay etiqueta, se hace PUT https://salesiq.zoho.com/api/v2/desarrollemonos/conversations/<id>/tags con la conexión salesiq_conn.

Constante Cuándo
TAG_DESBLOQUEO_OK (…674215) Activación exitosa o cuenta ya activa
TAG_DESBLOQUEO_FAIL (…674217) Rinde Plus rechazó el desbloqueo
TAG_TELEFONO_OK (…674211) Cambio exitoso o número ya registrado
TAG_TELEFONO_FAIL (…674213) Rinde Plus rechazó el cambio

4. Sistemas y dependencias

Sistema Uso Acceso Notas
Rinde Plus Admin Login POST /auth/login-sin-captcha Límite de 5 intentos cada 15 s
Rinde Plus Admin Verificar DPI y obtener nombres POST /auth/usuarios/verificar-dpi existe = 1 solo si hay un usuario único
Rinde Plus Admin Desbloquear cuenta POST /auth/usuarios/desbloquear message si ya estaba activa
Rinde Plus Admin Cambiar celular POST /auth/usuarios/cambiar-celular message si el número no cambió
Zoho AI OCR de la foto zoho.ai.recognizeText Hasta 20 MB y 40 s
SalesIQ REST Etiquetas PUT /api/v2/desarrollemonos/conversations/<id>/tags Conexión salesiq_conn

Base de Rinde Plus: https://rinde-plus-admin.somosdonarturo.com/api/admin (constante BASE_RINDE).

5. Credenciales y configuración

Nombre Tipo Dónde se guarda
RINDE_USER / RINDE_PASS Usuario de servicio de Rinde Plus Constantes al inicio del context_handler (líneas 29–30). En esta copia vienen vacías
salesiq_conn Conexión de Zoho Configurada en SalesIQ
IDs de etiquetas Constantes TAG_* Líneas 34–37

6. Estados y datos persistentes

Elemento Uso
context_id Operación, intento y, en el cambio de número, el DPI
answers Respuestas del contexto actual; se pierde al cambiar de contexto
Etiquetas de la conversación Resultado del trámite

El bot no guarda la foto ni los datos personales fuera de la conversación.

7. Manejo de errores y reintentos

Tipo Ejemplo Comportamiento
Negocio DPI con formato inválido Se vuelve a pedir, sin llamar a la API
Negocio Foto ilegible Se vuelve a pedir, sin consumir intento
Negocio Identidad no validada reintento_<op>_<n>, hasta 3 intentos
Negocio Teléfono que no tiene 8 dígitos Se vuelve a pedir
Aplicación Rinde Plus rechaza el desbloqueo o el cambio Etiqueta _FAIL y contexto de reintento
Infraestructura Login fallido o límite 429 end: "Intenta más tarde"
Infraestructura Excepción no controlada error_handler: mensaje y forward
Defensivo context_id desconocido Vuelve al menú en lugar de fallar con "No proper response"

8. Monitoreo y notificaciones

Las etiquetas de resultado son la fuente de métricas en SalesIQ: activaciones y cambios exitosos o rechazados.

Logs de prueba en el código, que se mantienen a propósito como referencia para depurar:

Línea Log Contenido
310 OCR_TEXTO Texto completo que leyó el OCR
370 [PRUEBA] op… Operación, intento, existe, CUI leído y resultado de cada comparación
574 [PRUEBA] cambiar-celular Respuesta completa de Rinde Plus
727 TAG Respuesta del etiquetado

Están marcados "QUITAR ANTES DE PRODUCCIÓN", pero se dejan como guía de qué revisar al probar. Se ven solo en los registros de ejecución del Zobot e incluyen el DPI y el texto del documento.

9. Restricciones conocidas y trampas

El archivo de la foto solo vale en el turno siguiente

El objeto files solo se puede usar en el turno inmediato a la subida. No se debe agregar ninguna pregunta entre la foto y el bloque de OCR.

Logins que no aceptan respuesta en lista

El login de la verificación de DPI contempla que Deluge devuelva la respuesta envuelta en una lista. Los logins de la validación final (línea 224) y del cambio de número (línea 540) no. Si ese caso ocurre, el usuario recibe "Intenta más tarde" justo después de enviar la foto o el número.

La comparación de nombre es por contenido

Se valida con contains, así que basta que lo escrito aparezca dentro del registro: "ANA" pasa contra "MARIANA". El control fuerte es el DPI de la foto; el nombre es solo una validación adicional.

El menú principal toma cualquier texto como activación

Si el texto de opcion no contiene "teléfono", se asume activar. Un usuario que escribe en lugar de presionar un botón entra al flujo de activación.

Opciones de cierre distintas

Tras activar la cuenta se ofrece "Contactar con agente"; tras cambiar el número, no. El texto de cuenta ya activa menciona "Contactar a agente", que no coincide con el botón.

10. Cómo aplicar cambios

Al terminar cualquiera: copiar el Deluge a flujos/, actualizar sincronizado_el en meta.yml y hacer commit con el número de ticket.

10.1 Agregar un trámite nuevo al menú
  1. Agrega la opción en menuQuestion (context_handler) y en message_handler; el menú está en los dos.
  2. En menu_principal, asigna un nuevo valor de op según el texto.
  3. Si el trámite requiere identidad, reutiliza validar_<op>_<n> y agrega su rama en la decisión final.
  4. Si necesita un contexto propio, usa un prefijo que no empiece igual que otro (regla de startsWith) y pasa en el nombre lo que deba sobrevivir.
  5. Crea sus etiquetas OK/FAIL y agrégalas como constantes TAG_*.
  6. Agrega el contexto al mapa del encabezado.
10.2 Cambiar el número de intentos

Cambia intento < 3 en los dos contextos de reintento (cuatro apariciones). Si llega a 10 o más, hay que cambiar también la lectura del intento, que hoy toma un dígito.

10.3 Cambiar textos del menú

El saludo está en message_handler y la pregunta del menú en menuQuestion. Si cambias el texto de un botón, revisa las comparaciones: "teléfono", "menú" y "agente" se buscan con containsIgnoreCase.

10.4 Cambiar una etiqueta

Crea la etiqueta en SalesIQ y reemplaza el ID en la constante TAG_*.

10.5 Un usuario dice que la validación falla con datos correctos
  1. Revisa en los registros del Zobot el log [PRUEBA] op… de esa conversación.
  2. cui vacío: el OCR no leyó el número (foto). dpi ok: false: el número leído es otro. declarado ok: false: nombre o apellido no aparecen en Rinde Plus tal como los escribió.
  3. existe: 0: el DPI no está registrado o está duplicado; se revisa en Rinde Plus.
10.6 Cambió la contraseña del usuario de servicio

Actualiza RINDE_PASS en el Zobot publicado (no en el repositorio) y prueba un trámite completo.

11. Historial de cambios

Versión Fecha Cambio Autor
1.0 2026-10-08 Documento inicial a partir del código Angel