Commit Graph
421 Commits
Author SHA1 Message Date
Lizandro Guarnizo 9e5a7017e1 portal enfermero: ver formularios paciente + fix orden médica .bin via descargar_orden.php 2026-03-17 15:04:35 -05:00
Lizandro Guarnizo 23bda70cb8 firma: tabs canvas/foto, drag&drop, fallback seguro, aviso builder 2026-03-17 13:34:18 -05:00
Lizandro Guarnizo 775c654790 cambios 2026-03-17 12:58:42 -05:00
Lizandro Guarnizo 262009f4e5 Update descargar_orden.php 2026-03-16 22:02:11 -05:00
Lizandro Guarnizo 0fddff6c5b up 2026-03-16 21:55:23 -05:00
Lizandro Guarnizo 4106840a39 up 2026-03-16 21:33:01 -05:00
Lizandro Guarnizo fe1d3c31b3 foto 2026-03-16 21:00:39 -05:00
Lizandro Guarnizo 79bcc5e4bf up 2026-03-16 20:46:54 -05:00
Lizandro Guarnizo 3b834bc24b up 2026-03-16 20:35:02 -05:00
Lizandro Guarnizo 5f7cc67dd9 up 2026-03-16 20:29:21 -05:00
Lizandro Guarnizo 8907f8fa95 up 2026-03-16 20:14:22 -05:00
Lizandro Guarnizo 07febbfd7e Update lab_domicilios.php 2026-03-16 20:05:32 -05:00
Lizandro Guarnizo 8b2e294636 Update lab_formulario_builder.php 2026-03-16 18:37:22 -05:00
Lizandro Guarnizo ded19cbb8d Cambios 2026-03-16 18:36:11 -05:00
Lizandro Guarnizo bbfe0417df up 2026-03-14 12:52:45 -05:00
Lizandro Guarnizo 405a3751e7 fix: T&C tab - quitar display:none y agregar case terms en loadTabData 2026-03-14 00:09:26 -05:00
Lizandro Guarnizo cf6743fbbd fix: corregir URL de upload binario a graph.facebook.com/{version}/{session_id} 2026-03-14 00:01:34 -05:00
Lizandro Guarnizo 9bdcdc91d8 fix: usar Resumable Upload API para foto de perfil WhatsApp 2026-03-14 00:00:26 -05:00
Lizandro Guarnizo 0b9744e9ef fix: eliminar cierre de funcion duplicado en app_simple.js 2026-03-13 23:57:30 -05:00
Lizandro Guarnizo 032219a4b6 fix: cerrar funcion toggleAdminUserStatus antes de las funciones de perfil WA 2026-03-13 23:55:40 -05:00
Lizandro Guarnizo 7df05ee3fb feat: perfil WhatsApp (foto, about, datos) y reset+sync de plantillas 2026-03-13 23:50:30 -05:00
Lizandro Guarnizo 290cdcc7ff fix: detectar rechazo T&C primero para evitar falso positivo con 'no acepto' 2026-03-13 23:39:39 -05:00
Lizandro Guarnizo 0987329a9b fix: sendWelcomeMessage no envía si términos no han sido aceptados 2026-03-13 23:36:51 -05:00
Lizandro Guarnizo 3d3c37fa18 fix: al aceptar T&C ir directo al menu, no enviar bienvenida por separado 2026-03-13 23:32:18 -05:00
Lizandro Guarnizo 94c6110e07 fix: welcome solo se envía si ya aceptó términos 2026-03-13 23:22:20 -05:00
Lizandro Guarnizo 95f83444a0 fix: system_config toma prioridad sobre terms_versions para mensajes T&C 2026-03-13 23:17:15 -05:00
Lizandro Guarnizo abfab22c35 fix: advisory lock por usuario en processMessage para eliminar race condition
- GET_LOCK('bot_user_ID', 10) serializa el procesamiento por usuario
- Solo un proceso a la vez puede ejecutar processMessage para el mismo user
- Recarga datos frescos del usuario tras adquirir el lock
- El lock se libera siempre en el bloque finally, incluso si hay excepciones
- Resuelve definitivamente el doble envío de bienvenida + términos
2026-03-13 19:33:31 -05:00
Lizandro Guarnizo bcfaf62293 fix: deduplicar webhooks duplicados con INSERT IGNORE + UNIQUE index en message_id
- conversations.message_id ahora tiene UNIQUE index (aplicado en BD prod)
- saveMessage() usa INSERT IGNORE: si el mismo wamid llega dos veces en
  paralelo solo una llamada procesa el mensaje y llama al bot
- La segunda llamada recibe rowCount=0 y hace continue sin pasar al bot
- Elimina race condition que enviaba bienvenida + términos simultáneamente
2026-03-13 19:22:34 -05:00
Lizandro Guarnizo 80e9cb43db fix: normalizar http/https al comparar URL del PDF para evitar duplicado 2026-03-13 19:16:10 -05:00
Lizandro Guarnizo 0e9c6935d8 fix: evitar doble saludo y URL duplicada en mensaje de términos
- sendTermsMessage: solo agrega PDF al final si la URL no está ya en el mensaje
- sendTermsMessage: marca welcome_sent_at=now() junto con terms_pending=1
  para evitar race condition donde un segundo webhook concurrente cae en
  isNewUser() y envía la bienvenida mientras los términos ya fueron enviados
2026-03-13 19:10:43 -05:00
Lizandro Guarnizo 46a9d97a07 fix: eliminar polling get_last_webhook_time (innecesario en index.php) 2026-03-13 18:47:21 -05:00
Lizandro Guarnizo 8df007d3de fix: actualizar APP_URL por defecto a bot.laboratorioximenacaicedo.com 2026-03-13 16:09:20 -05:00
Lizandro Guarnizo 730e1e9636 fix: accion ENUM en lab_autorizaciones al crear orden
El metodo registrarCambioEstado usaba estadoNuevo ('pendiente')
como valor de accion, pero pendiente no es un valor valido del
ENUM de lab_autorizaciones.accion.

Se pasa 'creada' explicitamente al crear una orden nueva, que si
es un valor valido del ENUM ('creada','en_revision','autorizada',
'rechazada','en_domicilio','completada','editada').
2026-03-13 15:53:42 -05:00
Lizandro Guarnizo 5211d83e8b fix: eliminar polling get_notifications en index.php + debug wamid en broadcast
- index.php: NotificationManager simplificado a stub vacío.
  Los elementos notification-bell / global-notification-toasts no existen en el
  markup → el setInterval cada 7s solo generaba tráfico inútil a get_notifications.php
  Las notificaciones ya se manejan vía SSE en conversations.php

- send_broadcast.php: exponer debug_wamids en respuesta (wamid, wa_status, wa_contact)
  para saber exactamente qué devuelve WhatsApp por cada destinatario.
  Agregar dryRun log del payload completo al error_log para diagnóstico de
  mensajes que WhatsApp acepta (200+wamid) pero no entrega.
2026-03-13 15:26:14 -05:00
Lizandro Guarnizo 6cdc7bd6c4 fix: corregir verificación de éxito en send_broadcast.php
La API de WhatsApp NO devuelve {success:true} - devuelve
{messaging_product, messages:[{id:wamid.xxx}], contacts:[...]}.
La comprobación anterior siempre fallaba → sent_count=0, error_count=N.
Ahora verifica presencia de messages/contacts en la respuesta.
2026-03-13 13:36:50 -05:00
Lizandro Guarnizo e081dc739a feat: soporte de imagen dinámica en plantillas WhatsApp
- Detecta header_type=IMAGE en get_template_details.php
- send_message (individual): muestra input de imagen si la plantilla lo requiere,
  sube a upload_media.php y envía header_image_url al backend
- broadcast (masivo): igual, con upload previo al envío
- api/send_message.php: acepta header_image_url y lo pasa como headerParameters
  [type:image, image:{link:URL}] a WhatsAppService::sendTemplateMessage()
- api/send_broadcast.php: igual para cada destinatario del masivo
- Preview en tiempo real de la imagen seleccionada en ambos formularios
2026-03-13 13:24:22 -05:00
Lizandro Guarnizo 027c8a6f26 fix: tipo_servicio hardcodeado como 'domicilio' en portal enfermero 2026-03-13 13:15:03 -05:00
Lizandro Guarnizo 7cc29fac1e fix: quitar campo Tipo de servicio del portal enfermero 2026-03-13 13:12:00 -05:00
Lizandro Guarnizo 4bcfd585cd fix: enf-nombre muestra nombre real desde sesión PHP (no queda en Cargando…) 2026-03-13 09:03:31 -05:00
Lizandro Guarnizo b8b4bffde2 feat: sesiones minimizadas múltiples — píldoras con nombre de chat y navegación 2026-03-13 08:57:10 -05:00
Lizandro Guarnizo e9c8cf7d9b feat: crear nuevo paciente desde modal de agendamiento (enfermero portal) 2026-03-12 23:18:31 -05:00
Lizandro Guarnizo 2b46057ac1 feat: modal agendar domicilio es minimizable y arrastrable 2026-03-12 23:16:14 -05:00
Lizandro Guarnizo 5c4ddd1cd8 fix: portal enfermero — agendamiento siempre particular, sin campo seguro 2026-03-12 23:04:34 -05:00
Lizandro Guarnizo 702323f852 fix: corrección portal enfermero — pagos y agendamiento
- fix: portal.renderAgenda → portal._renderLista() (error JS al registrar pago)
- feat: modal nueva agenda añade tipo_cliente (particular/seguro), seguro_nombre, autorizacion, valor_domicilio, valor_copago
- feat: toggleSeguro() muestra/oculta campo EPS según tipo seleccionado
- fix: abrir() resetea todos los campos nuevos en cada apertura del modal
- datos de cobro se envían al guardar y se auto-asigna la enfermera creadora
2026-03-12 23:02:48 -05:00
Lizandro Guarnizo eaebda9fe7 feat: edición completa de domicilio desde panel detalle
- Modal expandido: tipo_cliente, seguro, autorizacion, valor_domicilio, valor_copago, copago_laboratorio, indicaciones, fecha, hora, tipo_servicio, notas
- Botón Editar en header del panel detalle (aparece al seleccionar un domicilio)
- editarDomicilio(id): carga y pre-rellena todos los campos del modal
- toggleSeguro(): muestra/oculta campo seguro_nombre según tipo_cliente
- Tras guardar, el detalle se refresca automáticamente
2026-03-12 23:00:25 -05:00
Lizandro Guarnizo beb1bbe1d4 feat: sistema de pagos domicilios — cobro enfermero y estado pago admin
- database/07_add_pago_domicilio.sql: 6 columnas nuevas en lab_domicilios
  (pago_estado ENUM, pago_modo, pago_monto, pago_fecha, pago_notas, pago_registrado_por)
- Domicilio::filtrarCampos(): permite guardar campos de pago vía actualizar()
- Enfermera::agenda(): incluye valor_domicilio, valor_copago, pago_estado, pago_modo, pago_monto, pago_notas
- api/lab/registrar_pago.php: endpoint POST para registrar/actualizar pago del domicilio
- enfermero_portal.php: bloque cobro en card, modal registrar pago (efectivo/transferencia/exento), objeto pagoModal JS
- lab_domicilios.php: badge pago //🔵 en fila tabla, sección pago detallada en panel lateral
2026-03-12 22:53:24 -05:00
Lizandro Guarnizo c42e0976d7 fix: enfermero_portal - mostrar imagen de la orden aunque no esté vinculada al domicilio
Si lab_domicilios.orden_id es NULL (domicilio creado antes del fix
o desde otro flujo), usa subquery para encontrar la orden más reciente
del mismo paciente que tenga local_file.

Así el enfermero siempre ve la imagen de la orden del paciente
independientemente de cómo se agendó el domicilio.
2026-03-12 22:38:48 -05:00
Lizandro Guarnizo 8956de8eaa fix: ruta doble en local_file al mostrar imagen de orden médica
La BD guarda local_file con 'uploads/media/...' incluido.
El código le añadía otro 'uploads/media/' dando ruta doble.

- lab_ordenes.php: helper _resolveImg() detecta si el path
  ya empieza con 'uploads/' y no añade el prefijo de nuevo
- enfermero_portal.php: nueva función resImg() con misma lógica,
  usada en _cardHTML() al renderizar la imagen de la orden
2026-03-12 22:23:15 -05:00
Lizandro Guarnizo d362598a70 feat: relacionar imagen de WhatsApp con orden médica al agendar domicilio
Al abrir el modal desde una imagen en el chat:
- guardar() crea primero la OrdenMedica via crear_desde_whatsapp.php
  y pasa el orden_id resultante a save_domicilio.php
- Enfermera::agenda() hace LEFT JOIN a lab_ordenes_medicas para traer
  local_file de la orden asociada (as orden_local_file)
- enfermero_portal._cardHTML() muestra la imagen de la orden médica
  con link para ampliar
2026-03-12 22:14:04 -05:00
Lizandro Guarnizo 12e7b411d7 feat: enfermero_portal - mostrar todos los datos del paciente en tarjeta de domicilio
La tarjeta ahora muestra: documento, fecha de nacimiento, EPS,
teléfono (clickeable), correo (clickeable), exámenes solicitados
y tipo de cliente (particular/seguro con nombre del seguro).

Cambios:
- Enfermera::agenda() amplía SELECT con email, fecha_nacimiento,
  numero_documento, tipo_documento, eps, examenes_solicitados,
  tipo_cliente, seguro_nombre, ciudad, indicaciones_dir, notas_admin
- my_agenda.php simplificado: ya no re-consulta lab_domicilios por
  los campos que ahora vienen directo en la query
- enfermero_portal.php _cardHTML() muestra todos los campos nuevos
2026-03-12 22:05:47 -05:00