Skip to main content

Overview

The Appointments module manages the scheduling system for Nguhöe EHR. It includes doctor availability checking, conflict prevention, status management, and patient self-booking through the patient portal.
Appointments are accessible to Admin, Doctor, and Receptionist roles. Patients can book their own appointments through a dedicated portal.

Appointment Data Model

Core Fields

FieldTypeDescription
patient_idforeign keyReference to patient
doctor_idforeign keyReference to doctor (users table)
start_timedatetimeAppointment start time
end_timedatetimeAppointment end time
statusstringCurrent appointment status
reasonstringReason for visit
notestextAdditional notes

Appointment Statuses

Initial state when appointment is created

Scheduling Workflow

Staff Booking (Admin/Receptionist/Doctor)

1

Navigate to Appointments

Access the appointments module from the main menu
2

Click Create Appointment

Open the appointment creation form
3

Select Patient

Choose from existing patients or create a new patient first
4

Select Doctor

Choose the doctor for the appointment
5

Choose Date and Time

Pick available date/time slot
6

Add Details

Include reason for visit and any notes
7

Submit

Create the appointment
Route: appointments.storeAppointmentController@store
Action: CreateAppointmentAction
// Creating an appointment (AppointmentController.php:59-73)
$validated = $request->validate([
    'patient_id' => 'required|exists:patients,id',
    'doctor_id' => 'required|exists:users,id',
    'start_time' => 'required|date',
    'end_time' => 'required|date|after:start_time',
    'reason' => 'nullable|string|max:255',
    'notes' => 'nullable|string',
]);

$action->execute($validated);

Patient Self-Booking

Patients can book their own appointments through the patient portal (routes/web.php:64-72):
1

Access Portal

Navigate to “My Appointments” in patient portal
2

Click Book Appointment

Access the booking interface
3

Select Doctor

Choose preferred doctor
4

Pick Date

Select appointment date
5

View Available Slots

System displays available 30-minute time slots
6

Select Time and Confirm

Choose a slot and submit booking
Route: patient.appointments.storePatientPortalController@storeAppointment
Endpoint: POST /book-appointment
// Patient booking with automatic slot calculation
$start_time = Carbon::createFromFormat('Y-m-d H:i', $request->date . ' ' . $request->time);
$end_time = $start_time->copy()->addMinutes(30);

$action->execute([
    'patient_id' => $patient->id,
    'doctor_id' => $request->doctor_id,
    'start_time' => $start_time,
    'end_time' => $end_time,
    'status' => 'scheduled',
    'reason' => $request->reason,
]);

Doctor Availability System

How Availability Works

The system checks doctor schedules and existing appointments to determine available slots: API Endpoint: GET /api/availability
Controller: PatientPortalController@getAvailability
// Get availability for a specific doctor and date (PatientPortalController.php:39-95)
$request->validate([
    'doctor_id' => 'required|exists:users,id',
    'date' => 'required|date_format:Y-m-d',
]);

// 1. Get doctor's schedule for the day of week
$schedule = DoctorSchedule::where('user_id', $doctor_id)
    ->where('day_of_week', $dayOfWeek)
    ->first();

// 2. If doctor doesn't work that day, return empty
if (!$schedule || !$schedule->is_working) {
    return response()->json(['slots' => []]);
}

// 3. Generate 30-minute slots between start and end time
// 4. Check each slot against existing appointments
// 5. Mark slots as available or occupied

Conflict Prevention

The system prevents double-booking through overlap detection:
// Check for scheduling conflicts (PatientPortalController.php:118-124)
$conflict = Appointment::where('doctor_id', $request->doctor_id)
    ->where(function($query) use ($start_time, $end_time) {
        $query->where('start_time', '<', $end_time)
              ->where('end_time', '>', $start_time);
    })
    ->whereIn('status', ['scheduled', 'confirmed', 'completed'])
    ->exists();

if ($conflict) {
    return redirect()->back()->withErrors(['time' => 'Este horario ya no está disponible.']);
}
Only appointments with status scheduled, confirmed, or completed block time slots. Cancelled and no-show appointments don’t prevent booking.

Viewing and Filtering Appointments

Staff View

Staff can view and filter appointments (AppointmentController.php:18-42):
// Doctors only see their own appointments
if ($request->user()->hasRole('doctor')) {
    $query->where('doctor_id', $request->user()->id);
}

// Filter by doctor (admin/receptionist)
if ($request->has('doctor_id')) {
    $query->where('doctor_id', $request->get('doctor_id'));
}

// Filter by date
if ($request->has('date')) {
    $query->whereDate('start_time', $request->get('date'));
}
Route: appointments.indexAppointmentController@index

Patient View

Patients see only their own appointments: Route: patient.appointmentsPatientPortalController@appointments
Endpoint: GET /my-appointments

Updating Appointments

Update appointment status and details: Route: appointments.updateAppointmentController@update
Action: UpdateAppointmentAction
// Allowed updates (AppointmentController.php:78-90)
$validated = $request->validate([
    'status' => 'sometimes|in:scheduled,confirmed,completed,cancelled,no_show',
    'start_time' => 'sometimes|date',
    'end_time' => 'sometimes|date|after:start_time',
    'notes' => 'nullable|string',
]);
Updating appointment times re-validates availability to prevent conflicts.

Calendar View

Appointments display in a calendar interface showing:
  • Daily, weekly, and monthly views
  • Color-coded by status
  • Doctor filtering
  • Quick status updates

Relationships

// Appointment.php relationships

// Belongs to Patient
public function patient(): BelongsTo
{
    return $this->belongsTo(Patient::class);
}

// Belongs to Doctor (User)
public function doctor(): BelongsTo
{
    return $this->belongsTo(User::class, 'doctor_id');
}

Access Control

  • View all appointments
  • Create appointments for any patient/doctor
  • Update any appointment
  • Delete appointments
  • Filter by doctor and date
  • View only their own appointments
  • Create appointments with themselves
  • Update appointment status
  • Cannot delete appointments
  • View all appointments
  • Create appointments for any patient/doctor
  • Update appointment status
  • Delete appointments
  • View only their own appointments
  • Book new appointments through patient portal
  • Cannot modify or cancel through portal

Database Schema

CREATE TABLE appointments (
    id BIGINT PRIMARY KEY,
    patient_id BIGINT NOT NULL REFERENCES patients(id) ON DELETE CASCADE,
    doctor_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    start_time DATETIME NOT NULL,
    end_time DATETIME NOT NULL,
    status VARCHAR(255) DEFAULT 'scheduled',
    reason VARCHAR(255),
    notes TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    deleted_at TIMESTAMP
);

Best Practices

Confirm Appointments

Change status to ‘confirmed’ when patients confirm attendance

Update Status Promptly

Mark as ‘completed’ or ‘no_show’ after appointment time

Use Notes Field

Add important information like special requirements

Regular Schedule Updates

Keep doctor schedules current for accurate availability

Build docs developers (and LLMs) love