Documentación: menús y respuestas del bot, y manual de domicilios

El análisis de completitud cruzando roles contra módulos y tablas contra
documentos encontró dos huecos reales.

Manual de domicilios: recepcionista, lab_recepcion y lab_readonly tienen acceso
a la pantalla administrativa de domicilios, y la única página sobre el tema era
la del portal del enfermero, restringida a enfermeros. Son pantallas distintas
—una ve todo, la otra solo lo propio— y ahora cada una tiene su guía. Los
enfermeros pasan también a ver el manual de formularios, que su rol habilita.

Menús y respuestas automáticas del bot: había cuatro tablas en uso que ninguna
página explicaba. El bot responde solo las preguntas frecuentes mediante
autoresponses (7 configuradas) y ofrece un menú interactivo de 21 opciones en
dos niveles, todo configurable desde la base sin desplegar código. También
quedan documentados el estado de conversación, los envíos masivos y las
encuestas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-04 12:04:27 -05:00
co-authored by Claude Opus 5
parent 74e219e2ae
commit bc318db129
6 changed files with 178 additions and 1 deletions
@@ -71,6 +71,7 @@ Un turno **nunca se borra**. Si el paciente no aparece se marca *ausente*; si no
- [Recepción](?m=soporte&v=documentacion&s=manual&d=recepcion) - [Recepción](?m=soporte&v=documentacion&s=manual&d=recepcion)
- [Chat de WhatsApp](?m=soporte&v=documentacion&s=manual&d=chat-whatsapp) - [Chat de WhatsApp](?m=soporte&v=documentacion&s=manual&d=chat-whatsapp)
- [Órdenes médicas](?m=soporte&v=documentacion&s=manual&d=ordenes-medicas) - [Órdenes médicas](?m=soporte&v=documentacion&s=manual&d=ordenes-medicas)
- [Domicilios](?m=soporte&v=documentacion&s=manual&d=domicilios)
- [Formularios](?m=soporte&v=documentacion&s=manual&d=formularios) - [Formularios](?m=soporte&v=documentacion&s=manual&d=formularios)
- [Reportes y métricas](?m=soporte&v=documentacion&s=manual&d=reportes) - [Reportes y métricas](?m=soporte&v=documentacion&s=manual&d=reportes)
- [Toma de muestras](?m=soporte&v=documentacion&s=manual&d=toma-de-muestras) - [Toma de muestras](?m=soporte&v=documentacion&s=manual&d=toma-de-muestras)
@@ -35,6 +35,15 @@ La línea de WhatsApp del laboratorio la atiende un bot, pero cuando hace falta
Lo importante: **cuando toma una conversación, el bot deja de responder ahí**. No hay riesgo de que le conteste encima al paciente mientras usted está escribiendo. Lo importante: **cuando toma una conversación, el bot deja de responder ahí**. No hay riesgo de que le conteste encima al paciente mientras usted está escribiendo.
## Lo que el bot resuelve solo
Antes de llegar a una persona, el bot responde por su cuenta las preguntas más
frecuentes —precios, horarios, ubicación, indicaciones previas— y ofrece un menú
numerado para agendar, consultar resultados o ver el portafolio.
Ese contenido es configurable: si una respuesta quedó desactualizada o hace falta
una nueva, un administrador la cambia sin necesidad de programar nada.
## Atender una conversación ## Atender una conversación
La lista muestra los hilos con mensajes recientes. Al abrir uno ve el historial completo y puede responder. La lista muestra los hilos con mensajes recientes. Al abrir uno ve el historial completo y puede responder.
@@ -0,0 +1,64 @@
---
roles: recepcionista, lab_recepcion, lab_readonly, supervisor
---
# Domicilios
La pantalla administrativa de las visitas domiciliarias: agendarlas, asignarles enfermero y seguirlas.
> Es distinta del **portal del enfermero**. Aquí se ve y administra todo; el portal muestra a cada enfermero solo lo suyo y está pensado para el celular.
## Agendar una visita
1. **Paciente** — búsquelo por cédula. Si no existe, se crea en el momento.
2. **Dirección** — la de su ficha con un botón, o escriba otra. Agregue indicaciones si el lugar es difícil de ubicar.
3. **Fecha y hora**.
4. **Servicio** — qué se va a hacer.
5. **Seguro y autorización**, si aplica.
6. **Valores** — domicilio y copago.
## Asignar un enfermero
Una visita agendada queda **sin asignar** hasta que se le pone un enfermero. Las sin asignar del día son las que hay que resolver primero: nadie las va a atender solo porque estén agendadas.
Al asignarla, la visita aparece en el portal de ese enfermero, que puede editarla.
## Estados
```
┌────────────┐ ┌───────────┐ ┌──────────────┐
│ programado ├──►│ en curso ├──►│ completado │
└─────┬──────┘ └───────────┘ └──────────────┘
└────────────────────────► ┌──────────────┐
│ cancelado │
└──────────────┘
```
## Notas y archivos
Cada visita admite notas de seguimiento, con fotos y archivos adjuntos. Sirve para dejar la orden médica en papel, un resultado o una observación de lo ocurrido.
Las notas quedan visibles para quien atienda después. Es el lugar correcto para dejar constancia de algo que el próximo necesita saber.
## Formularios
Se le puede enviar un formulario al paciente para que lo firme desde su celular, o copiar el enlace para hacérselo llegar por otro medio. Los ya firmados se consultan desde la misma visita.
## Si solo tiene permiso de lectura
Algunos roles ven los domicilios sin poder modificarlos: no aparecen los botones de crear ni editar. Puede consultar la agenda, el estado de cada visita y sus notas.
## Preguntas frecuentes
**Agendé una visita y el enfermero dice que no la ve.**
Verifique que le haya asignado el enfermero. Sin asignación, la visita no aparece en ningún portal.
**Hay que reprogramar.**
Edite la fecha y la hora, y avísele al paciente. Desde el portal del enfermero hay un enlace que abre WhatsApp con el mensaje ya redactado.
**El paciente cambió de dirección.**
Edite la visita. Si el cambio es permanente, actualice también la ficha del paciente, o la próxima vez volverá a aparecer la anterior.
**¿Puedo ver los domicilios de todos los enfermeros?**
Desde esta pantalla sí. El portal, en cambio, muestra a cada enfermero solo los suyos.
@@ -1,5 +1,5 @@
--- ---
roles: formularios_readonly, supervisor roles: formularios_readonly, enfermero, supervisor
--- ---
# Formularios # Formularios
@@ -54,6 +54,12 @@ $rawComps = [
Si el envío por plantilla falla, se manda un texto plano con el enlace armado desde el dominio del servidor. Ese texto **no** pasa por Meta, así que su URL puede diferir de la del botón. Si el envío por plantilla falla, se manda un texto plano con el enlace armado desde el dominio del servidor. Ese texto **no** pasa por Meta, así que su URL puede diferir de la del botón.
## Contenido configurable
Buena parte de lo que responde el bot vive en la base, no en el código: respuestas
automáticas por palabra clave y menús interactivos. Ver
[Menús y respuestas automáticas](?m=soporte&v=documentacion&s=tecnica&d=bot-menus-y-respuestas).
## `BotService` ## `BotService`
Decide qué hacer con cada mensaje entrante: Decide qué hacer con cada mensaje entrante:
@@ -0,0 +1,97 @@
# Menús y respuestas automáticas del bot
Buena parte de lo que responde el bot **no está en el código**: es contenido configurable en la base. Cambiar lo que contesta no requiere tocar PHP ni desplegar.
## Respuestas automáticas
`autoresponses` — dispara una respuesta según lo que escriba el paciente.
| Columna | Para qué |
|---|---|
| `trigger_type` | Cómo se dispara: `welcome`, `keyword`, `contains` |
| `trigger_value` | Las palabras que la activan, separadas por coma |
| `response_text` | Lo que responde |
| `response_type` | `text` o plantilla |
| `template_name` | Plantilla de Meta, si aplica |
| `menu_id` | Si en vez de texto debe mostrar un menú |
| `priority` | Cuál gana si varias coinciden |
| `is_active` | Permite desactivar sin borrar |
### Tipos de disparo
| Tipo | Cuándo actúa |
|---|---|
| `welcome` | Primer contacto |
| `keyword` | El mensaje **es** una de las palabras listadas |
| `contains` | El mensaje **contiene** el texto |
`keyword` es más estricto que `contains`. Para *«hola»* conviene `keyword` — si fuera `contains` se dispararía dentro de cualquier frase que la incluya.
### Las que están activas
Cubren saludo, precios, horarios, indicaciones previas, cotización y preparación para frotis. Son las preguntas que más se repiten, resueltas sin intervención humana.
## Menús interactivos
`menu_options` — el árbol de opciones numeradas que el paciente recorre respondiendo con un número.
| Columna | Para qué |
|---|---|
| `menu_id` | A qué menú pertenece la opción |
| `option_number` | El número que marca el paciente |
| `text` | Lo que se muestra |
| `action_type` | Qué pasa al elegirla |
| `action_value` | El destino o el texto de respuesta |
| `is_active` | Permite ocultar sin borrar |
### Acciones
| `action_type` | Efecto |
|---|---|
| `menu` | Abre otro menú — `action_value` es su identificador |
| `end` | Responde con `action_value` y cierra |
| `message` | Envía el texto y sigue en el mismo menú |
### La estructura actual
```
main_menu (1)
├─ 1 Agendar toma a domicilio end
├─ 2 Consultar resultados end
├─ 3 Información sobre exámenes ─────► menu informacion_examenes (10)
│ ├─ 1 Pruebas de embarazo end
│ ├─ 2 Prueba de paternidad message
│ ├─ 3 Pruebas de aliento end
│ ├─ 4 Orina de 24 horas end
│ ├─ 5 Solicitar cotización end
│ └─ 6 Volver ──────────────────► main_menu
├─ 4 Ubicación y horarios end
├─ 5 Ver portafolio end
├─ 6 Convenios end
└─ 7 Salir end
```
> Un menú se apunta por su **identificador** (`main_menu`, `informacion_examenes`), no por su número de fila. Cambiar el orden no rompe los enlaces.
## Estado de la conversación
`user_states` recuerda en qué punto quedó cada paciente: en qué menú está, si espera un dato, o si lo tomó un operador. Es lo que permite que responder «3» signifique algo.
Es la tabla más voluminosa del bot — una fila por contacto activo.
## Envíos masivos
`broadcast_history` registra los envíos a varios destinatarios a la vez.
> Fuera de la ventana de 24 horas hay que usar plantilla aprobada. Un envío masivo a contactos que no escribieron recientemente **solo puede hacerse con plantilla**.
## Encuestas
`survey_responses` guarda las respuestas de satisfacción. La encuesta se envía desde el historial del turnero con la plantilla `encuesta_turnero`.
## Al modificar el bot
- **Primero mire si alcanza con la base.** Muchos cambios de comportamiento son una fila en `autoresponses` o `menu_options`, sin desplegar nada.
- **Use `is_active` en vez de borrar.** Permite volver atrás y conserva el historial.
- **Cuide `priority`.** Si dos respuestas coinciden, gana la de mayor prioridad; sin ella el resultado depende del orden de la consulta.
- **Verifique el árbol completo** después de tocar un menú: una opción que apunta a un menú inexistente deja al paciente sin salida.