Skip to main content

Overview

The clinical records system maintains detailed medical histories and treatment documentation for each patient. It consists of two main components: clinical files (Expediente Clínico) with baseline medical history, and evolution notes (Notas de Evolución) that document treatment progress.

Medical History

Comprehensive baseline health records for each patient

Evolution Notes

Session-by-session treatment documentation

One-to-One Files

Each patient has exactly one clinical file

Treatment Linked

Evolution notes tied to specific treatments

Clinical Files (Expediente Clínico)

The clinical file stores the patient’s baseline medical information that remains relatively stable over time.

Data Model

See model at ~/workspace/source/app/Models/ExpedienteClinico.php

Database Schema

See migration at ~/workspace/source/database/migrations/2026_02_23_092325_create_expediente_clinico_table.php:14-34
Schema::create('expediente_clinico', function (Blueprint $table) {
    $table->id('id_expediente');
    
    // One-to-one relationship with patient
    $table->unsignedBigInteger('id_paciente')->unique();
    
    // Medical history fields
    $table->text('antecedentes_hereditarios')->nullable();
    $table->text('antecedentes_patologicos')->nullable();
    $table->text('alergias')->nullable();
    $table->text('observaciones_generales')->nullable();
    
    $table->date('fecha_registro')->nullable();
    
    $table->timestamps();
    
    // Foreign key with cascade delete
    $table->foreign('id_paciente')
          ->references('id_paciente')
          ->on('paciente')
          ->onDelete('cascade');
});

Model Attributes

See fillable fields at ~/workspace/source/app/Models/ExpedienteClinico.php:17-24
FieldTypeDescription
id_expedientebigintPrimary key
id_pacientebigintForeign key to patient (unique)
antecedentes_hereditariostextHereditary medical conditions
antecedentes_patologicostextPersonal pathological history
alergiastextKnown allergies
observaciones_generalestextGeneral observations
fecha_registrodateDate of file creation
The id_paciente field has a unique constraint, ensuring each patient has exactly one clinical file.

Medical History Components

Hereditary History (Antecedentes Hereditarios)

Records family medical history relevant to dental care:

Diabetes

Family history of diabetes (affects healing, periodontal disease)

Hypertension

High blood pressure (anesthesia considerations)

Hemophilia

Bleeding disorders (extraction risks)

Cancer

Family cancer history (oral cancer screening)
Example:
"Padre diabético tipo 2. Madre con hipertensión controlada. 
Abuela materna con osteoporosis."

Pathological History (Antecedentes Patológicos)

Patient’s personal medical conditions:
  • Diabetes mellitus
  • Hypertension
  • Heart disease
  • Kidney disease
  • Liver conditions
  • Autoimmune disorders
Current medications that may affect dental treatment:
  • Anticoagulants (bleeding risk)
  • Bisphosphonates (osteonecrosis risk)
  • Immunosuppressants (infection risk)
  • Corticosteroids (healing impairment)
Relevant surgical history:
  • Previous dental surgeries
  • Heart valve replacements (antibiotic prophylaxis)
  • Joint replacements (infection concerns)
Example:
"Hipertensión arterial diagnosticada 2020, controlada con Losartán 50mg/día.
No cirugías previas. Niega hospitalización reciente."

Allergies (Alergias)

Critical for treatment safety:
Allergy information is life-critical. Document:
  • Specific allergen
  • Type of reaction
  • Severity
  • Date of last reaction

Medications

Penicillin, NSAIDs, local anesthetics

Materials

Latex, metals (nickel, mercury)

Other

Food allergies, environmental allergies
Example:
"Alergia a penicilina (rash cutáneo, 2018).
No alergias a anestésicos locales.
Alergia ambiental a polen (controlada)."

General Observations (Observaciones Generales)

Additional relevant information:
  • Smoking/alcohol habits
  • Dental anxiety or phobias
  • Special needs or accommodations
  • Language barriers
  • Pregnancy status
  • Breastfeeding status
Example:
"Fumador: 10 cigarrillos/día x 15 años.
Alta ansiedad dental, requiere manejo conductual.
Preferencia por citas matutinas."

Relationship with Patient

See relationship at ~/workspace/source/app/Models/ExpedienteClinico.php:27-31
// ExpedienteClinico belongs to one patient
public function paciente()
{
    return $this->belongsTo(Paciente::class, 'id_paciente', 'id_paciente');
}
From the Patient side:
// Patient has one clinical file
public function expediente()
{
    return $this->hasOne(ExpedienteClinico::class, 'id_paciente', 'id_paciente');
}

Creating a Clinical File

Clinical files are typically created when a patient first registers:
public function store(Request $request)
{
    $validated = $request->validate([
        'id_paciente' => 'required|exists:paciente,id_paciente|unique:expediente_clinico,id_paciente',
        'antecedentes_hereditarios' => 'nullable|string',
        'antecedentes_patologicos' => 'nullable|string',
        'alergias' => 'nullable|string',
        'observaciones_generales' => 'nullable|string',
    ]);
    
    $expediente = ExpedienteClinico::create([
        'id_paciente' => $validated['id_paciente'],
        'antecedentes_hereditarios' => $validated['antecedentes_hereditarios'],
        'antecedentes_patologicos' => $validated['antecedentes_patologicos'],
        'alergias' => $validated['alergias'],
        'observaciones_generales' => $validated['observaciones_generales'],
        'fecha_registro' => now()->toDateString()
    ]);
    
    return redirect()->route('pacientes.show', $validated['id_paciente'])
        ->with('success', 'Expediente clínico creado correctamente.');
}

Combined Patient and File Creation

Often created together in a transaction:
DB::transaction(function () use ($request) {
    // 1. Create patient
    $paciente = Paciente::create([
        'nombre' => $request->nombre,
        'apellido_paterno' => $request->apellido_paterno,
        // ... other patient fields
    ]);
    
    // 2. Create clinical file
    ExpedienteClinico::create([
        'id_paciente' => $paciente->id_paciente,
        'antecedentes_hereditarios' => $request->antecedentes_hereditarios,
        'antecedentes_patologicos' => $request->antecedentes_patologicos,
        'alergias' => $request->alergias,
        'observaciones_generales' => $request->observaciones_generales,
        'fecha_registro' => now()->toDateString()
    ]);
});

Updating Clinical Files

Medical history should be updated when new information becomes available:
public function update(Request $request, $id)
{
    $expediente = ExpedienteClinico::findOrFail($id);
    
    $validated = $request->validate([
        'antecedentes_hereditarios' => 'nullable|string',
        'antecedentes_patologicos' => 'nullable|string',
        'alergias' => 'nullable|string',
        'observaciones_generales' => 'nullable|string',
    ]);
    
    $expediente->update($validated);
    
    return redirect()->back()
        ->with('success', 'Expediente actualizado correctamente.');
}
Consider implementing version history or audit logs for clinical file changes to maintain a complete record of modifications.

Evolution Notes (Notas de Evolución)

Evolution notes document treatment progress session by session.

Data Model

See model at ~/workspace/source/app/Models/NotasEvolucion.php

Database Schema

See migration at ~/workspace/source/database/migrations/2026_02_23_093121_create_notas_evolucion_table.php
Schema::create('notas_evolucion', function (Blueprint $table) {
    $table->id('id_nota');
    
    $table->unsignedBigInteger('id_tratamiento');
    $table->unsignedBigInteger('id_usuario');
    
    $table->date('fecha');
    $table->time('hora');
    $table->text('nota_texto');
    $table->text('indicaciones')->nullable();
    
    $table->timestamps();
    
    // Foreign keys
    $table->foreign('id_tratamiento')
          ->references('id_tratamiento')->on('tratamiento')
          ->onDelete('cascade');
    
    $table->foreign('id_usuario')
          ->references('id_usuario')->on('usuario')
          ->onDelete('cascade');
});

Model Attributes

See fillable fields at ~/workspace/source/app/Models/NotasEvolucion.php:17-24
FieldTypeDescription
id_notabigintPrimary key
id_tratamientobigintTreatment being documented (required)
id_usuariobigintDentist writing the note (required)
fechadateNote date
horatimeNote time
nota_textotextClinical note content (required)
indicacionestextPost-treatment instructions

Evolution Note Components

Clinical Note (nota_texto)

Documents what was done during the session:
Example:
S: Paciente refiere dolor moderado en molar inferior derecho.
O: Caries profunda en pieza #46, sensible a percusión. 
   Radiografía muestra compromiso pulpar.
A: Pulpitis irreversible en #46.
P: Endodoncia iniciada. Apertura cameral, conductometría realizada.
   Medicación intraconducto (hidróxido de calcio).
   Obturación temporal.

Instructions (indicaciones)

Post-treatment patient instructions:

Medications

Analgesics, antibiotics, anti-inflammatories

Care Instructions

Oral hygiene, dietary restrictions, activity limits

Warning Signs

When to call/return to clinic

Follow-up

Next appointment scheduling
Example:
- Tomar ibuprofeno 400mg cada 8 horas por 3 días
- Evitar masticar del lado tratado
- Mantener buena higiene oral
- Cita de seguimiento en 7 días para obturación definitiva
- Llamar si presenta inflamación excesiva o fiebre

Relationships

Belongs to Treatment

See relationship at ~/workspace/source/app/Models/NotasEvolucion.php:27-31
public function tratamiento()
{
    return $this->belongsTo(Tratamiento::class, 'id_tratamiento', 'id_tratamiento');
}

Belongs to Usuario (Dentist)

See relationship at ~/workspace/source/app/Models/NotasEvolucion.php:33-37
public function usuario()
{
    return $this->belongsTo(Usuario::class, 'id_usuario', 'id_usuario');
}

Creating Evolution Notes

Notes are created after each treatment session:
public function store(Request $request)
{
    $validated = $request->validate([
        'id_tratamiento' => 'required|exists:tratamiento,id_tratamiento',
        'nota_texto' => 'required|string',
        'indicaciones' => 'nullable|string',
    ]);
    
    $nota = NotasEvolucion::create([
        'id_tratamiento' => $validated['id_tratamiento'],
        'id_usuario' => auth()->user()->id_usuario,
        'fecha' => now()->toDateString(),
        'hora' => now()->toTimeString(),
        'nota_texto' => $validated['nota_texto'],
        'indicaciones' => $validated['indicaciones']
    ]);
    
    return redirect()->route('tratamientos.show', $validated['id_tratamiento'])
        ->with('success', 'Nota de evolución registrada.');
}

Viewing Treatment History

Display all notes for a treatment chronologically:
// Controller
$tratamiento = Tratamiento::with([
    'notasEvolucion' => function($query) {
        $query->orderBy('fecha', 'desc')
              ->orderBy('hora', 'desc');
    },
    'notasEvolucion.usuario',
    'paciente',
    'catalogoTratamiento'
])->findOrFail($id);

return view('tratamientos.show', compact('tratamiento'));
{{-- View --}}
<h2>Historial de Notas de Evolución</h2>

@foreach($tratamiento->notasEvolucion as $nota)
<div class="nota-evolucion">
    <div class="nota-header">
        <strong>{{ $nota->fecha }} {{ substr($nota->hora, 0, 5) }}</strong>
        <span>Dr. {{ $nota->usuario->nombre }}</span>
    </div>
    
    <div class="nota-contenido">
        <h4>Nota Clínica:</h4>
        <p>{{ $nota->nota_texto }}</p>
        
        @if($nota->indicaciones)
        <h4>Indicaciones:</h4>
        <p>{{ $nota->indicaciones }}</p>
        @endif
    </div>
</div>
@endforeach

Complete Patient Medical Record View

Combine clinical file with treatment history:
$paciente = Paciente::with([
    'expediente',
    'tratamiento' => function($q) {
        $q->with(['catalogoTratamiento', 'notasEvolucion.usuario'])
          ->orderBy('fecha_inicio', 'desc');
    }
])->findOrFail($id);
This provides:
  1. Baseline medical history (expediente)
  2. All treatments (current and historical)
  3. Complete treatment evolution notes
  4. Chronological medical timeline

Entity Relationship Diagram

Best Practices

Create the expediente during patient registration, even if some fields are empty. It’s easier to update than to create later.
Allergies are critical safety information. Update the clinical file immediately when discovered and display prominently in the UI.
Create an evolution note after every treatment session, no matter how minor. This creates:
  • Legal protection
  • Continuity of care
  • Quality assurance
  • Patient communication record
Adopt SOAP or similar structured format for consistency:
  • Easier to read
  • More complete documentation
  • Better for legal purposes
  • Facilitates data extraction
In evolution notes, document:
  • Tooth numbers (using FDI notation: #11-#48)
  • Anesthesia used and dose
  • Materials used
  • Patient tolerance
  • Complications or deviations from plan
Patient instructions (indicaciones) should:
  • Be clear and specific
  • Include medication names and dosages
  • List warning signs
  • Specify follow-up timing
Use actual session date/time, not creation time of the note if entered later:
// If documenting after the fact
'fecha' => $request->fecha_sesion, // Not now()
'hora' => $request->hora_sesion,   // Not now()
Clinical records are legal documents. Ensure:
  1. Retention: Store indefinitely or per local regulations (often 5-10 years after last visit)
  2. Privacy: Comply with health information privacy laws (HIPAA in US, LFPDPPP in Mexico)
  3. Integrity: Never delete notes. Use soft deletes or amendments if corrections needed
  4. Access Control: Limit who can view/edit clinical records
  5. Backup: Regular automated backups of all clinical data

Querying Clinical Records

Patients with Specific Allergies

$pacientesAlergicos = ExpedienteClinico::where('alergias', 'LIKE', '%penicilina%')
    ->with('paciente')
    ->get();

Patients with Diabetes (Risk Assessment)

$diabeticos = ExpedienteClinico::where(function($q) {
    $q->where('antecedentes_hereditarios', 'LIKE', '%diabetes%')
      ->orWhere('antecedentes_patologicos', 'LIKE', '%diabetes%');
})
->with('paciente')
->get();

Recent Evolution Notes by Dentist

$notasRecientes = NotasEvolucion::where('id_usuario', $dentistaId)
    ->whereBetween('fecha', [now()->subDays(30), now()])
    ->with(['tratamiento.paciente', 'tratamiento.catalogoTratamiento'])
    ->orderBy('fecha', 'desc')
    ->get();

Complete Patient Timeline

// Combine appointments and evolution notes for complete timeline
$paciente = Paciente::with([
    'expediente',
    'citas' => function($q) {
        $q->orderBy('fecha', 'desc');
    },
    'tratamiento.notasEvolucion'
])->find($id);

// Merge and sort by date for unified timeline
$timeline = collect()
    ->merge($paciente->citas)
    ->merge($paciente->tratamiento->flatMap->notasEvolucion)
    ->sortByDesc('fecha');

Patient Management

Manage patients who own clinical records

Treatments

Treatments documented in evolution notes

Appointments

Sessions that generate evolution notes

Build docs developers (and LLMs) love