Lógica Backend

Motor de disponibilidad, callouts, procesos y validaciones por evento.

Motor de Disponibilidad

AppointmentAvailabilityEngine concentra la lógica que decide si una cita o un slot es válido para un empleado, servicio y fecha determinados.

Responsabilidades actuales

Regla de conflicto

Una cita se considera en conflicto cuando otra cita activa del mismo empleado se cruza con el rango nuevo y tiene estado pendiente o aprobado.

existing.StartDateTime < newEnd
AND existing.EndDateTime > newStart
AND existing.Status IN ('PE', 'AP')
AND existing.IsActive = 'Y'

Generación de slots

La generación actual es específica por empleado. El proceso no genera para todos los empleados ni autoasigna el recurso; parte de una selección explícita de empleado, servicio y fecha.

Nota: esta decisión hace que el flujo de UI sea más claro: primero se elige quién atiende, luego qué servicio presta, después se generan horarios disponibles.

Reglas actuales vs reglas esperadas

ReglaEstado actualComportamiento esperado
Empleado presta servicioImplementado con CDS_EmployeeService.Se mantiene como regla obligatoria.
Día libre de organizaciónImplementado por organización. Aunque CDS_OrgDayOff tiene CDS_AppointmentConfig_ID, el motor actual no filtra por configuración.Debe filtrar por configuración cuando el servicio resuelva una configuración específica.
Día libre de empleadoImplementado con CDS_EmployeeDayOff.Se mantiene como bloqueo específico del empleado.
Horario del empleadoImplementado con CDS_EmployeeScheduleLine.Debe validarse después del horario macro de la configuración.
Horario macro de agendaPendiente. No existe aún una tabla equivalente a horario de configuración.Debe definir los días y rangos generales permitidos, por encima del horario del empleado.
Anticipación mínimaPendiente. Existe MinAdvanceHours, pero no se valida todavía.Debe bloquear citas creadas con menos horas de anticipación que las configuradas.
Anticipación máximaPendiente. Existe MaxAdvanceDays, pero no se valida todavía.Debe bloquear citas demasiado futuras.
Conflictos con citas existentesImplementado para estados Pending y Approved.Se mantiene como validación obligatoria.
Aprobación automática o forzadaPendiente. Existen campos de configuración y servicio, pero no se aplican en el evento.Debe resolverse en BeforeNew usando configuración y servicio.

Roadmap del motor

Callouts y Flujo de UI

CalloutAppointment ayuda al usuario a capturar una cita desde iDempiere sin reemplazar la validación final del backend.

Comportamiento de callouts

CampoComportamiento
CDS_AppointmentService_IDCopia precio y duración efectivos. Si existe empleado seleccionado, usa override de CDS_EmployeeService. Limpia slot y horas, pero no limpia empleado.
AppointmentDateLimpia slot, hora inicial y hora final. No limpia empleado ni servicio.
CDS_AppointmentSlot_IDCopia empleado, hora inicial, hora final, precio y duración desde el slot seleccionado.

Flujo recomendado en ventana

  1. Seleccionar el empleado que atenderá la cita.
  2. Seleccionar el servicio filtrado para ese empleado.
  3. Seleccionar la fecha de la cita.
  4. Ejecutar el proceso de generación de slots.
  5. Seleccionar el slot generado.
  6. Guardar la cita.

Importante: si un usuario modifica manualmente horas, precio o duración, el evento de modelo vuelve a validar la consistencia antes de guardar.

Procesos y Eventos

El plugin mantiene pocos procesos activos y concentra las reglas críticas en eventos de modelo.

Procesos activos

ProcesoUso
GenerateAppointmentSlotsGenera registros CDS_AppointmentSlot para el empleado, servicio y fecha seleccionados. Puede resolver valores desde la cita actual cuando se ejecuta desde la ventana.
ReopenAppointmentReabre una cita procesada cambiándola a pendiente y limpiando Processed mediante un contexto controlado.

Proceso GenerateAppointmentSlots

Este proceso se usa para crear horarios disponibles persistentes que luego pueden consultarse desde la ventana iDempiere o desde la API leyendo la tabla CDS_AppointmentSlot.

ParámetroRequeridoUso
AD_Org_IDSí, directo o resuelto desde la citaOrganización para cargar configuración y validar disponibilidad.
CDS_AppointmentEmployee_IDEmpleado para el cual se generan slots.
CDS_AppointmentService_IDServicio que define duración, precio e intervalo del slot.
AppointmentDateFecha para la cual se generan horarios disponibles.
CDS_Appointment_IDOpcionalSi se ejecuta desde una cita, permite resolver organización, empleado, servicio y fecha desde el registro actual.

Antes de generar nuevos slots, el proceso desactiva slots previos activos del usuario actual. Si hay una cita, desactiva los slots asociados a esa cita. Si no hay cita, desactiva slots del mismo usuario, empleado, servicio y fecha.

Uso recomendado: desde la ventana de cita se selecciona empleado, servicio y fecha; luego se ejecuta GenerateAppointmentSlots; finalmente se selecciona un registro de CDS_AppointmentSlot.

Proceso ReopenAppointment

Este proceso reabre una cita procesada para permitir correcciones administrativas controladas.

ParámetroRequeridoUso
CDS_Appointment_IDSí, directo o resuelto desde el registro actualCita procesada que se desea reabrir.

Si la cita ya está abierta, el proceso informa que no requiere reapertura. Si está procesada, activa un contexto temporal #CDS_ReopenAppointment, coloca Processed=N y cambia el estado a Pending.

Validación por evento actual

AppointmentModelValidator se ejecuta antes de crear o cambiar una cita. Para citas pendientes o aprobadas valida los datos mínimos y la disponibilidad real.

Estados y procesamiento actual

Roadmap de validaciones en eventos

Las siguientes reglas deben agregarse al evento para que el comportamiento sea consistente desde ventanas iDempiere y desde REST/API.

Validación pendienteMomento sugeridoRegla esperada
Resolver configuración desde servicioBeforeNew y BeforeChangeEl servicio debe indicar qué configuración de agenda aplica. La cita usa esa configuración para anticipación, horario macro y aprobación.
Servicio con una sola configuraciónAl guardar servicio o relación configuración-servicioUn servicio no debe estar asociado a más de una configuración activa.
Anticipación mínimaBeforeNew y generación de slotsSi StartDateTime está antes de ahora + MinAdvanceHours, la cita o slot debe bloquearse.
Anticipación máximaBeforeNew y generación de slotsSi StartDateTime supera hoy + MaxAdvanceDays, la cita o slot debe bloquearse.
Horario macro de configuraciónBeforeNew, BeforeChange y generación de slotsEl horario de agenda general debe contener el rango solicitado antes de evaluar el horario del empleado.
Forzar aprobaciónBeforeNewSi la configuración tiene ForceApproval=Y, la cita debe quedar pendiente aunque el servicio permita aprobación automática.
Autoaprobar si el servicio lo permiteBeforeNewSi AutoApproveIfServiceAllows=Y y el servicio no requiere aprobación, la cita puede quedar Approved.

Roadmap de workflows y correos

Además de las validaciones, falta definir workflows y plantillas de correo para notificar al cliente cuando cambie el estado de una cita.

Flujo pendienteDisparo sugeridoResultado esperado
Notificar cita aprobadaCambio de estado a Approved.Enviar correo al cliente con fecha, hora, servicio y empleado.
Notificar cita canceladaCambio de estado a Cancelled.Enviar correo al cliente con el motivo de cancelación cuando exista.
Notificar reprogramaciónCambio de fecha, hora o empleado.Enviar correo con el nuevo horario confirmado.
Recordatorio de citaProceso programado antes de StartDateTime.Enviar recordatorio al cliente según configuración.

También falta crear las plantillas de correo, definir destinatarios, configurar remitente, parametrizar cuándo enviar cada notificación y evitar reenvíos duplicados con campos de control si aplica.

Orden recomendado de validación

  1. Resolver servicio, empleado y organización.
  2. Resolver configuración de agenda desde el servicio.
  3. Aplicar reglas de anticipación mínima y máxima.
  4. Validar horario macro de configuración.
  5. Validar días libres de organización vinculados a la configuración.
  6. Validar relación empleado-servicio.
  7. Validar horario y días libres del empleado.
  8. Validar slot seleccionado.
  9. Validar conflictos con citas existentes.
  10. Resolver estado de aprobación: pendiente o aprobada.