Skip to main content

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.

The services module lets clinic administrators define reusable clinical service workflows — structured sequences of stages that staff must complete in order, with optional evidence requirements and deadline tracking for each stage. Once defined, a service can be contracted for an individual patient; the system snapshots the current stage definitions at the moment of contracting, so future edits to the template never disrupt in-progress patient journeys.

Three-Layer Service Hierarchy

Services are organized in three nested layers:
LineaServicio (Service Line)
  └─► Servicio (Service)
        └─► ServicioEtapa (Stage 1 → 2 → 3 → …)
LineaServicio is the top-level grouping category. For example, a clinic might have lines like “Cardiología”, “Cirugía Estética”, or “Medicina General”. Each line has a nombre, optional descripcion, and an activo flag. Servicio is the clinical service itself — the thing a patient actually contracts. It belongs to a LineaServicio and holds scheduling and billing metadata. ServicioEtapa represents one step within the service workflow, ordered by orden. Steps run sequentially; a stage cannot be completed if any preceding stage is still pending.

Servicio Field Reference

nombre
string
required
Human-readable service name, e.g., “Consulta Inicial de Cardiología”.
linea_servicio_id
integer
required
Foreign key to the parent LineaServicio.
precio
decimal
Agreed price for this service. Used as the default precio_acordado when contracting for a patient.
duracion_minutos
integer
Expected total service duration in minutes. Passed to the appointment scheduler when booking a consultation for this service.
permite_recurrencia
boolean
When true, the appointment form allows this service to be booked as a recurring series.
activo
boolean
Controls visibility. Inactive services are hidden from reception and patient-facing views via scopeActivos.
descripcion
string
Long-form description shown to staff when browsing the catalog.
requerimientos
string
Pre-appointment requirements or patient instructions (nullable free text).

scopeActivos — Catalog Filtering

Servicio::scopeActivos() adds WHERE activo = true to any query. Non-admin roles always see the filtered catalog; the Administrador Clinica role sees all services (active and inactive) so deactivated services can be reactivated when needed:
// ServicioController::index()
$query = Servicio::with(['lineaServicio', 'staffPerfiles', 'etapas']);

if (! $esAdmin) {
    $query->activos(); // only active services for non-admins
}

ServicioEtapa — Stage Definition

Each stage on a service template carries:
nombre
string
required
Stage name (e.g., “Toma de muestras”, “Revisión médica”).
orden
integer
Execution order (1-based). Stages are always processed in ascending order.
requiere_evidencia
boolean
When true, the staff member must attach a file to mark the stage complete.
tipo_evidencia
string
Description of what evidence is expected (e.g., “Foto”, “PDF de laboratorio”).
plazo_horas
integer
Hours allowed to complete this stage from the moment the previous one was finished. Triggers deadline tracking on PacienteServicioEtapa.vence_at.
notificar_roles
array
JSON array of Spatie role names that receive an email alert when this stage fails or expires. Defaults to ["Doctor","Recepcion"].

ServicioStaffPerfil — Authorized Roles

Each Servicio can have one or more ServicioStaffPerfil records, each holding a single Spatie role_name. These define which roles are authorized to complete or fail stages on that service:
// Servicio::rolesPermitidos()
public function rolesPermitidos(): array
{
    return $this->staffPerfiles()->pluck('role_name')->toArray();
}
Authorization is enforced in PacienteServicioController::autorizarEjecucion(): the request user must either be an Administrador Clinica or hold one of the roles listed in servicio_staff_perfiles.

Setting Up a New Service

1

Create a Service Line

Navigate to the Admin Dashboard → Services tab. Click Nueva Línea de Servicio and provide a nombre and optional descripcion. The line must be active to appear in the service creation form.
POST /{tenant}/lineas-servicio
Body: { "nombre": "Cardiología", "descripcion": "..." }
2

Create the Service

Within the service line, click Nuevo Servicio. Supply the nombre, precio, duracion_minutos, whether it permite_recurrencia, and select at least one authorized role in roles[].
POST /{tenant}/servicios
Body: {
  "linea_servicio_id": 1,
  "nombre": "Consulta Inicial",
  "precio": 850.00,
  "duracion_minutos": 45,
  "permite_recurrencia": false,
  "roles": ["Doctor", "Enfermero"]
}
3

Define the Stage Workflow

Include the etapas[] array in the same request (or via the edit form). Each stage object needs at minimum a nombre; add requiere_evidencia, plazo_horas, and notificar_roles as needed.
"etapas": [
  {
    "nombre": "Registro de signos vitales",
    "orden": 1,
    "requiere_evidencia": false,
    "plazo_horas": 1
  },
  {
    "nombre": "Revisión médica",
    "orden": 2,
    "requiere_evidencia": true,
    "tipo_evidencia": "Notas clínicas PDF",
    "plazo_horas": 24,
    "notificar_roles": ["Doctor", "Recepcion"]
  }
]
The entire service, its staff profiles, and its stages are created in a single database transaction.
4

Assign the Service to a Patient

From the patient’s detail page, a receptionist or admin selects the service and clicks Contratar. The system snapshots all currently-active stages from servicio_etapas into new paciente_servicio_etapas rows:
POST /{tenant}/pacientes/{paciente}/servicios
Body: { "servicio_id": 3 }
The PacienteServicio record is created with estado = en_progreso and precio_acordado set to the service’s current precio.

Stage Execution Lifecycle

Once a service is contracted, all stage tracking lives in paciente_servicio_etapas. Stages have these possible states: pendiente, completado, fallido.
[Stage 1: pendiente] ──► completado ──► [Stage 2: pendiente] ──► completado ──► …
                    └──► fallido ──► (service blocked) ──► reactivar ──► pendiente

Completing a Stage

PATCH /paciente-servicio-etapas/{etapa}/completar
  • The request must include evidencia (file) when requiere_evidencia = true.
  • The controller blocks completion if any earlier-ordered stage is not yet in completado state.
  • On success, the deadline (vence_at) for the next stage is recalculated from now().
  • When all stages of a PacienteServicio reach completado, the parent record’s estado is automatically updated to completado.

Failing a Stage

PATCH /paciente-servicio-etapas/{etapa}/fallar A notas field with the failure reason is required. Marking a stage as fallido also sets the parent PacienteServicio.estado to bloqueado and triggers email notifications to all roles listed in notificar_roles for that stage.

Reactivating a Failed Stage

PATCH /paciente-servicio-etapas/{etapa}/reactivar Only the Administrador Clinica role can reactivate a failed stage. This resets the stage to pendiente and restores the PacienteServicio.estado to en_progreso.

Progress Calculation

The PacienteServicio::progreso() method returns an integer from 0 to 100, calculated as the percentage of stages in completado state out of the total stages in the snapshot:
public function progreso(): int
{
    $total      = $this->etapas()->count();
    if ($total === 0) return 0;
    $completadas = $this->etapas()->where('estado', 'completado')->count();
    return (int) round(($completadas / $total) * 100);
}

Service Workflow Diagram

Admin creates LineaServicio


Admin creates Servicio (with etapas[] and roles[])


Recepcion/Admin contracts service for a patient  ← POST /pacientes/{id}/servicios


PacienteServicio created (estado: en_progreso)
  + PacienteServicioEtapa rows (snapshot of etapas)


Authorized staff works through stages in order
  PATCH .../completar  (+ evidencia if required)
  PATCH .../fallar     (requires notas)


All stages completado → PacienteServicio.estado = completado
Editing a service’s stage workflow after it has been contracted for patients does not affect those in-progress records. The stages for each contracted service are stored as a snapshot in paciente_servicio_etapas, completely independent of the template in servicio_etapas.

Route Reference

MethodPathDescriptionRequired Role
GET/serviciosList service catalog (active only for non-admins)Any authenticated
POST/serviciosCreate service with stages and staff rolesAdministrador Clinica
PATCH/servicios/{servicio}Edit service metadata, stages, and rolesAdministrador Clinica
PATCH/servicios/{servicio}/toggleActivate or deactivate a serviceAdministrador Clinica
DELETE/servicios/{servicio}Delete a service (blocked if patients are linked)Administrador Clinica
GET/lineas-servicioList service linesAdministrador Clinica
POST/lineas-servicioCreate a new service lineAdministrador Clinica
PATCH/lineas-servicio/{lineaServicio}Edit a service lineAdministrador Clinica
PATCH/lineas-servicio/{lineaServicio}/toggleActivate or deactivate a service lineAdministrador Clinica
DELETE/lineas-servicio/{lineaServicio}Delete a service lineAdministrador Clinica
GET/pacientes/{paciente}/serviciosList services contracted by a patientAny authenticated
POST/pacientes/{paciente}/serviciosContract a service for a patientAdministrador Clinica, Recepcion
PATCH/paciente-servicio-etapas/{etapa}/completarMark a stage as completedAuthorized roles per servicio_staff_perfiles
PATCH/paciente-servicio-etapas/{etapa}/fallarMark a stage as failedAuthorized roles per servicio_staff_perfiles
PATCH/paciente-servicio-etapas/{etapa}/reactivarReactivate a failed stageAdministrador Clinica

Build docs developers (and LLMs) love