The appointment module is the operational heart of XHealtXperience’s day-to-day clinic workflow. It supports individual and recurring consultation appointments, real-time conflict detection against both existing appointments and agenda blocks, an overbooking override mechanism with full audit trail, and a QR-based check-in flow that works both through an authenticated staff interface and an unauthenticated tablet kiosk placed in the waiting room.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Arthurr23/XHealtXperience/llms.txt
Use this file to discover all available pages before exploring further.
Appointment Lifecycle
Every appointment (Cita) moves through a defined set of statuses. The diagram below shows the normal path and the two terminal exception states:
| Status constant | Value | Description |
|---|---|---|
ESTATUS_PROGRAMADA | programada | Appointment has been booked but not yet confirmed. |
ESTATUS_CONFIRMADA | confirmada | Confirmed by the patient or clinic staff. |
ESTATUS_CHECKIN | checkin | Patient has checked in at the front desk. |
ESTATUS_EN_PROGRESO | en_progreso | Consultation or procedure is actively in progress. |
ESTATUS_COMPLETADA | completada | Appointment concluded. |
ESTATUS_CANCELADA | cancelada | Appointment was cancelled (with optional penalty). |
ESTATUS_NO_SHOW | no_show | Patient did not appear. |
ESTATUS_ACTIVOS is a convenience constant that groups programada, confirmada, checkin, and en_progreso — it is used throughout availability checks and dashboard queries to filter only live appointments.
Modalidad and Tipo de Cita
Two orthogonal classifiers describe every appointment:modalidad — how the appointment takes place:
presencial: In-person visit at the clinic.virtual: Remote/telemedicine consultation.
tipo_cita — what category of appointment this is:
consulta: A standard medical consultation. Created throughCitaController.cirugia: A surgical procedure. Created throughQuirofanoControllerand always requires aSalaof typequirofanoand aProcedimientoQuirurgico. See Surgical Suites for details.
Scheduling an Appointment
The appointment creation form is served atGET /citas/create and submitted to POST /citas. The controller middleware restricts creation to users with the roles Recepcion, Doctor, Administrador Clinica, or Administrador Profesionista.
You can either select an existing patient by ID (paciente_id) or supply minimal data for a new patient inline (nuevo_paciente.*). When creating a new patient inline, the status is automatically set to Pendiente.
Conflict Detection via DisponibilidadService
Before persisting a single appointment, the system calls DisponibilidadService::resumenConflictos(), which executes three independent overlap queries for the requested time window:
- Doctor conflict — active appointments assigned to the same
medico_idthat overlaphora_inicio/hora_fin. - Agenda block conflict —
BloqueoAgendarecords for the same doctor in the same window. - Room conflict — active appointments in the same
sala_idthat overlap the window.
null (clear to proceed). When creating a single appointment, conflicts cause the form to be returned with a conflicto_horario flash key so the React UI can display a warning modal.
When a staff member confirms overbooking by setting
overbooking_confirmado = true and providing a notas_override justification, the appointment is saved anyway and the overbooking flag is set to true on the record, with overbooking_aceptado_por pointing to the user who approved it. Use POST /citas/{cita}/resolver-conflicto to resolve a pending conflict on a recurring series occurrence — set accion to aceptar (keeps the appointment as overbooking) or cancelar (cancels that specific occurrence).Recurring Appointments
An appointment series is created by settinges_recurrente = true in the creation request. Recurrence is controlled by three fields:
How the series repeats:
semanal, quincenal, mensual, or personalizada.Used when
recurrencia_tipo is personalizada. The number of days between occurrences.The end date of the series (
YYYY-MM-DD). Used when recurrencia_metodo_fin is fecha_hasta.RecurrenciaService expands the start date into the full list of occurrence dates before the controller persists each one inside a single database transaction. The first occurrence becomes the “anchor” (cita_padre_id = null); all subsequent occurrences store its ID in cita_padre_id. Recurring series occurrences with schedule conflicts are not blocked — they are created with conflicto_pendiente = true for later manual review, and a count of flagged occurrences is included in the success flash message.
To cancel every future occurrence in a series at once, pass alcance = serie when calling CitaController::cancelar() once that route is available.
QR Token and Check-In
A UUID v4qr_token is generated automatically on every appointment creation via the creating Eloquent boot hook:
codigo_paciente, or phone number via GET /citas-pacientes/buscar?q=. The CitaController::checkin() and CitaController::buscarParaCheckin() methods are implemented and ready — the dedicated staff-side check-in routes will be registered in a future release.
Check-in updates the record:
Visitor Self Check-In (Unauthenticated Kiosk)
XHealtXperience provides a fully public check-in page suitable for a tablet mounted in the waiting room. No login is required. The route is protected instead by a long random token stored intenant_settings.visitor_checkin_token:
| Method | Path | Description |
|---|---|---|
GET | /citas/checkin/visitante/{token} | Renders the self-service check-in UI |
GET | /citas/checkin/visitante/{token}/buscar?q= | Searches today’s appointments (returns minimal fields only) |
POST | /citas/checkin/visitante/{token}/citas/{cita} | Confirms check-in for the matched appointment |
tenant_settings, all three endpoints return 403.
An Administrador Clinica can rotate the token at any time via POST /citas/checkin/visitante/regenerar — the previous URL is immediately invalidated.
Cancellation and Penalty Window
TheCita model exposes a helper method to determine whether a cancellation falls inside the 24-hour penalty window:
CitaController::cancelar() method is fully implemented and accepts the following payload. The dedicated cancellation route (POST /citas/{cita}/cancelar) is planned for a future release — cancellation is currently handled via the Quirófano controller for surgical appointments.
Reason for cancellation (max 1,000 characters). Always required.
Whether to flag a penalty. Only takes effect when the appointment is inside the 24-hour window; ignored otherwise. The penalty amount is read from
tenant_settings.monto_penalizacion_cancelacion.esta (default) cancels only this occurrence. serie cancels all future active occurrences in the same recurring series.penalizacion_aplica, penalizacion_monto, and penalizacion_cobrada are set on the record, allowing billing staff to track collection separately.
Drag-and-Drop Rescheduling
The calendar view supports drag-and-drop rescheduling viaPATCH /citas/{cita}/reprogramar. The duration is preserved; only fecha and hora_inicio change. Conflict detection runs the same way as during creation. Pass forzar = true to skip conflict checking and accept the overbooking.
Route Reference
Routes requireauth + two_factor + check_inactivity unless the “Required Role” column states otherwise.
| Method | Path | Description | Required Role |
|---|---|---|---|
GET | /citas | Outlook-style calendar view (day/week/month) | Recepcion, Doctor, Administrador Clinica, Administrador Profesionista |
GET | /citas/create | New appointment form | Recepcion, Doctor, Administrador Clinica, Administrador Profesionista |
POST | /citas | Create appointment (single or recurring) | Recepcion, Doctor, Administrador Clinica, Administrador Profesionista |
PATCH | /citas/{cita}/reprogramar | Drag-and-drop reschedule | Recepcion, Doctor, Administrador Clinica, Administrador Profesionista |
POST | /citas/{cita}/resolver-conflicto | Accept or cancel a pending series conflict | Recepcion, Doctor, Administrador Clinica, Administrador Profesionista |
GET | /citas-pacientes/buscar | Typeahead patient search for appointment form | Recepcion, Doctor, Administrador Clinica, Administrador Profesionista |
GET | /citas/checkin/visitante/{token} | Visitor self-check-in page | No auth required |
GET | /citas/checkin/visitante/{token}/buscar | Visitor appointment search | No auth required |
POST | /citas/checkin/visitante/{token}/citas/{cita} | Visitor check-in confirmation | No auth required |
POST | /citas/checkin/visitante/regenerar | Rotate visitor check-in token | Administrador Clinica |