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:
answersse limpia al cambiar decontext_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:
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.- Login y
POST /auth/usuarios/verificar-dpi. Siexiste ≠ 1, pasa areintento_<op>_<n>. Si existe, preguntanombre. apellido.foto: un archivo jpg, jpeg o png.- Con la foto:
- Nuevo login y nueva consulta a
verificar-dpipara obtener los nombres registrados (no hay dónde guardarlos entre turnos). - OCR con
zoho.ai.recognizeText(archivo)con el modelo por defecto. - 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. - Se normalizan nombre y apellido a mayúsculas sin acentos ni Ñ y se buscan dentro de los nombres y apellidos registrados.
- Nuevo login y nueva consulta a
- 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>)¶
- El DPI se toma del nombre del contexto (todo lo que va después de
<n>_). - Pide
telefono, deja solo dígitos y exige 8. - Login y
POST /auth/usuarios/cambiar-celularcondpiynuevoTelefono. ok = truees éxito; conmessage, el número ya era el registrado. Un fallo (409 número de otro usuario o DPI duplicado, 404, 400) va acambio_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ú
- Agrega la opción en
menuQuestion(context_handler) y enmessage_handler; el menú está en los dos. - En
menu_principal, asigna un nuevo valor deopsegún el texto. - Si el trámite requiere identidad, reutiliza
validar_<op>_<n>y agrega su rama en la decisión final. - 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. - Crea sus etiquetas OK/FAIL y agrégalas como constantes
TAG_*. - 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
- Revisa en los registros del Zobot el log
[PRUEBA] op…de esa conversación. cuivací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ó.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 |