Kulcare Docs
DeveloperAuthentication Documentation04 featuresSpeciality_modules

Medical Examination System Documentation

Overview

This document describes the comprehensive medical examination system implementation for dermatology, neurology, and cardiology examinations. The system follows the therapy notes pattern with independent examination models not tied to prescriptions, proper event-based appointment linking, and comprehensive validation rules.

Table of Contents

  1. API Endpoints
  2. Database Schema
  3. Models and Validations
  4. Controllers and Actions
  5. Interactors
  6. Serializers
  7. Patient History Integration
  8. Soft Delete Implementation

API Endpoints

Base Path

/clinic_patients/:clinic_patient_id/

Dermatology Examinations

GET    /derma_examinations          # Index all derma examinations
GET    /derma_examinations/:id      # Show specific derma examination
POST   /derma_examinations          # Create new derma examination
PUT    /derma_examinations/:id      # Update derma examination
DELETE /derma_examinations/:id      # Soft delete derma examination

Neurology Examinations

GET    /neuro_examinations          # Index all neuro examinations
GET    /neuro_examinations/:id      # Show specific neuro examination
POST   /neuro_examinations          # Create new neuro examination
PUT    /neuro_examinations/:id      # Update neuro examination
DELETE /neuro_examinations/:id      # Soft delete neuro examination

Cardiology Examinations

GET    /cardio_examinations          # Index all cardio examinations
GET    /cardio_examinations/:id      # Show specific cardio examination
POST   /cardio_examinations          # Create new cardio examination
PUT    /cardio_examinations/:id      # Update cardio examination
DELETE /cardio_examinations/:id      # Soft delete cardio examination

Database Schema

Entity Relationship Diagram

Models and Validations

Dermatology Examination Model

File: backend/parts/patient/models/derma_examination.rb

Columns and Validations

ColumnTypeValidationsAllowed Values
clinic_patient_idintegerpresence: true-
clinic_idintegerpresence: true-
doctor_idintegerpresence: true-
event_idintegeroptional-
event_typestringoptional'Appointment'
examination_sitestringinclusion, allow_blank'localized', 'generalized', 'symmetrical'
lesion_typestringinclusion, allow_blank'macule', 'papule', 'vesicle', 'pustule', 'plaque', 'nodule'
lesion_colorstringinclusion, allow_blank'erythematous', 'hyperpigmented', 'hypopigmented'
lesion_configurationstringinclusion, allow_blank'annular', 'linear', 'grouped', 'scattered'
surfacestringinclusion, allow_blank'smooth', 'scaly', 'crusted', 'ulcerated'
secondary_changesstringinclusion, allow_blank'excoriation', 'lichenification', 'atrophy', 'scar'
notestextlength: { maximum: 2000 }-
deletedboolean-false (default)
deleted_atdatetime--
deleted_by_user_idinteger--
deleted_reasontext--

Associations

belongs_to :clinic_patient
belongs_to :clinic
belongs_to :doctor
belongs_to :event, polymorphic: true, optional: true

Scopes

scope :active, -> { where(deleted: false) }
scope :order_by_latest, -> { order('created_at desc') }

Neurology Examination Model

File: backend/parts/patient/models/neuro_examination.rb

Columns and Validations

ColumnTypeValidationsAllowed Values
clinic_patient_idintegerpresence: true-
clinic_idintegerpresence: true-
doctor_idintegerpresence: true-
event_idintegeroptional-
event_typestringoptional'Appointment'
level_of_consciousnessstringinclusion, allow_blank'alert', 'drowsy', 'unconscious'
orientationstringinclusion, allow_blank'oriented', 'disoriented'
speechstringinclusion, allow_blank'normal', 'dysarthric', 'aphasic'
higher_functionsstringinclusion, allow_blank'normal', 'impaired'
cranial_nervesstringinclusion, allow_blank'normal', 'abnormal'
motor_systemstringinclusion, allow_blank'normal', 'weak', 'spastic', 'flaccid'
sensory_systemstringinclusion, allow_blank'normal', 'impaired'
reflexesstringinclusion, allow_blank'normal', 'brisk', 'diminished'
meningeal_signsstringinclusion, allow_blank'absent', 'present'
gaitstringinclusion, allow_blank'normal', 'ataxic', 'hemiplegic'
coordinationstringinclusion, allow_blank'normal', 'impaired'
tremorsstringinclusion, allow_blank'absent', 'present'
involuntary_movementsstringinclusion, allow_blank'absent', 'present'
neuro_examination_datajsonb--
deletedboolean-false (default)
deleted_atdatetime--
deleted_by_user_idinteger--
deleted_reasontext--

Associations

belongs_to :clinic_patient
belongs_to :clinic
belongs_to :doctor
belongs_to :event, polymorphic: true, optional: true

Cardiology Examination Model

File: backend/parts/patient/models/cardio_examination.rb

Columns and Validations

ColumnTypeValidationsAllowed Values
clinic_patient_idintegerpresence: true-
clinic_idintegerpresence: true-
doctor_idintegerpresence: true-
event_idintegeroptional-
event_typestringoptional'Appointment'
General Physical Examination
built_nutritionstringinclusion, allow_blank'normal', 'thin', 'obese'
pallor_cyanosis_clubbing_edemastringinclusion, allow_blank'present', 'absent'
systemic_appearancestringinclusion, allow_blank'comfortable', 'distressed', 'dyspneic'
Inspection
chest_shapestringinclusion, allow_blank'normal', 'barrel', 'pectus'
visible_pulsationsstringinclusion, allow_blank'present', 'absent'
surgical_scarsstringinclusion, allow_blank'present', 'absent'
jvd_peripheral_signsstringinclusion, allow_blank'present', 'absent'
Palpation
apex_beatstringinclusion, allow_blank'normal', 'displaced', 'heaving', 'tapping'
parasternal_heavestringinclusion, allow_blank'present', 'absent'
thrillstringinclusion, allow_blank'present', 'absent'
pulse_character_capillary_refillstringinclusion, allow_blank'normal', 'bounding', 'thready'
Percussion
cardiac_bordersstringinclusion, allow_blank'normal', 'shifted'
dullness_assessmentstringinclusion, allow_blank'normal', 'increased'
Auscultation
s1_s2_soundsstringinclusion, allow_blank'normal', 'soft', 'loud', 'split'
added_soundsstringinclusion, allow_blank'present', 'absent'
murmursstringinclusion, allow_blank'present', 'absent'
pericardial_rubstringinclusion, allow_blank'present', 'absent'
Additional Findings
jvpstringinclusion, allow_blank'normal', 'raised'
hepatomegalystringinclusion, allow_blank'present', 'absent'
edemastringinclusion, allow_blank'present', 'absent'
limb_bp_differencestringinclusion, allow_blank'present', 'absent'
peripheral_cyanosis_temperaturestringinclusion, allow_blank'normal', 'cold', 'warm'
Soft Delete Fields
deletedboolean-false (default)
deleted_atdatetime--
deleted_by_user_idinteger--
deleted_reasontext--

Controllers and Actions

All examination controllers follow the same pattern with CRUD operations (index, show, create, update, destroy) and use corresponding interactors for business logic.

Controller Files

ControllerFilePurpose
DermaExaminationsControllerbackend/parts/clinic/controllers/derma_examinations_controller.rbDermatology examination CRUD operations
NeuroExaminationsControllerbackend/parts/clinic/controllers/neuro_examinations_controller.rbNeurology examination CRUD operations
CardioExaminationsControllerbackend/parts/clinic/controllers/cardio_examinations_controller.rbCardiology examination CRUD operations

Interactors

Interactor Files

InteractorFilePurpose
DermaExaminationActions::Savebackend/parts/clinic/interactors/derma_examination_actions/save.rbCreate/update derma examinations
DermaExaminationActions::Deletebackend/parts/clinic/interactors/derma_examination_actions/delete.rbSoft delete derma examinations
NeuroExaminationActions::Savebackend/parts/clinic/interactors/neuro_examination_actions/save.rbCreate/update neuro examinations
NeuroExaminationActions::Deletebackend/parts/clinic/interactors/neuro_examination_actions/delete.rbSoft delete neuro examinations
CardioExaminationActions::Savebackend/parts/clinic/interactors/cardio_examination_actions/save.rbCreate/update cardio examinations
CardioExaminationActions::Deletebackend/parts/clinic/interactors/cardio_examination_actions/delete.rbSoft delete cardio examinations

All interactors follow the same pattern:

  • Validate clinic patient and doctor
  • Handle event-based appointment linking
  • Comprehensive validation with detailed error messages
  • Transaction-based saving for data consistency
  • Soft delete with audit trail

Serializers

Base Serializer Pattern

All serializers follow the same structure:

class ExaminationSerializer < ActiveModel::Serializer
  attributes :id, :clinic_patient_id, :doctor_id, :clinic_id, :event_id, :event_type,
             :examination_fields, :notes, :deleted, :deleted_at, :created_at, :updated_at

  has_one :doctor, serializer: DoctorSerializer
  has_one :clinic_patient, serializer: ClinicPatientSerializer
  has_one :event, polymorphic: true

  def examination_fields
    # Implementation varies by examination type
  end
end

Serializer Files

SerializerFilePurpose
DermaExaminationSerializerbackend/parts/clinic/serializers/patient_derma_examination_serializer.rbDermatology examination response formatting
NeuroExaminationSerializerbackend/parts/clinic/serializers/patient_neuro_examination_serializer.rbNeurology examination response formatting
CardioExaminationSerializerbackend/parts/clinic/serializers/patient_cardio_examination_serializer.rbCardiology examination response formatting

Patient History Integration

History Logging

All examination models include the PatientHistoryActivity concern and automatically log to patient history:

# In each examination model
include PatientHistoryActivity

after_save :save_patient_history

def save_patient_history
  return unless clinic_patient_id.present?

  PatientHistory::SaveHistory.perform_now(
    id,
    'EXAMINATION_TYPE'  # DERMA_EXAMINATION, NEURO_EXAMINATION, CARDIO_EXAMINATION
  )
end

Patient History Services

ServiceFilePurpose
SaveDermaExaminationbackend/parts/clinic/services/patient_history/save_derma_examination.rbLogs derma examination changes to patient history
SaveNeuroExaminationbackend/parts/clinic/services/patient_history/save_neuro_examination.rbLogs neuro examination changes to patient history
SaveCardioExaminationbackend/parts/clinic/services/patient_history/save_cardio_examination.rbLogs cardio examination changes to patient history

Soft Delete and Patient History

Soft deletes are handled using update_columns to bypass validations, with manual patient history logging:

def soft_delete!(user_id: nil, reason: nil)
  update_columns(
    deleted: true,
    deleted_at: Time.current,
    deleted_by_user_id: user_id,
    deleted_reason: reason
  )
  # Manually trigger patient history save for deletion since update_columns bypasses callbacks
  save_patient_history
end

API Request/Response Examples

Create Dermatology Examination

Request:

POST /api/v1/clinic_patients/17/derma_examinations
Content-Type: application/json

{
  "doctor_id": 8,
  "appointment_id": 424,
  "dermatology_examination_data": {
    "derma_examination_data": {
      "general_examination": "Patient appears alert and cooperative",
      "vitals": {
        "bp": "120/80 mmHg",
        "pulse": "72 bpm",
        "temperature": "98.6°F",
        "respiratory_rate": "16 cpm"
      },
      "systemic_examination": {
        "cardiovascular": "Normal S1,S2, no murmurs",
        "respiratory": "Bilateral air entry present, no adventitious sounds",
        "abdomen": "Soft, non-tender, no organomegaly"
      }
    },
    "examination_site": "localized",
    "lesion_type": "papule",
    "lesion_color": "erythematous",
    "lesion_configuration": "grouped",
    "surface": "smooth",
    "secondary_changes": "lichenification",
    "notes": "Patient presents with acne-like eruptions on the face and neck. Patient appears alert and cooperative. Vitals: BP 120/80 mmHg, pulse 72 bpm, temperature 98.6°F, respiratory rate 16 cpm. Systemic examination shows cardiovascular: normal S1,S2, no murmurs; respiratory: bilateral air entry present, no adventitious sounds; abdomen: soft, non-tender, no organomegaly."
  }
}

Create Cardiology Examination

Request:

POST /api/v1/clinic_patients/17/cardio_examinations
Content-Type: application/json

{
  "doctor_id": 8,
  "appointment_id": 424,
  "cardiology_examination_data": {
    "built_nutrition": "normal",
    "pallor_cyanosis_clubbing_edema": "absent",
    "systemic_appearance": "comfortable",

    "chest_shape": "normal",
    "visible_pulsations": "absent",
    "surgical_scars": "absent",
    "jvd_peripheral_signs": "absent",

    "apex_beat": "normal",
    "parasternal_heave": "absent",
    "thrill": "absent",
    "pulse_character_capillary_refill": "normal",

    "cardiac_borders": "normal",
    "dullness_assessment": "normal",

    "s1_s2_sounds": "normal",
    "added_sounds": "absent",
    "murmurs": "present",
    "pericardial_rub": "absent",

    "jvp": "normal",
    "hepatomegaly": "absent",
    "edema": "absent",
    "limb_bp_difference": "absent",
    "peripheral_cyanosis_temperature": "warm"
  }
}

Create Neurology Examination

Request:

POST /api/v1/clinic_patients/17/neuro_examinations
Content-Type: application/json

{
  "doctor_id": 8,
  "appointment_id": 424,
  "neurology_examination_data": {
    "level_of_consciousness": "alert",
    "orientation": "alert",
    "speech": "normal",
    "gait": "normal",
    "involuntary_movements": "none",
    "memory": "intact",
    "attention_concentration": "normal",
    "language": "normal",
    "mood_behavior": "normal",
    "olfactory": "normal",
    "optic": "normal",
    "oculomotor_group": "normal",
    "trigeminal": "normal",
    "facial": "normal",
    "vestibulocochlear": "normal",
    "glossopharyngeal_vagus": "normal",
    "accessory": "normal",
    "hypoglossal": "normal",
    "muscle_bulk": "normal",
    "tone": "normal",
    "power": "5",
    "reflexes": "biceps",
    "plantar_response": "flexor",
    "touch_sensation": "normal",
    "pain": "normal",
    "temperature": "normal",
    "vibration_sense": "normal",
    "joint_position_sense": "normal",
    "finger_nose_test": "normal",
    "rapid_alternating_movements": "normal",
    "coordination_gait": "normal",
    "romberg_test": "negative",
    "neck_stiffness": "absent",
    "kernigs_sign": "absent",
    "brudzinskis_sign": "absent",
    "localization": "Left parietal lobe",
    "probable_diagnosis": "Cerebrovascular Accident (Left MCA Territory)",
    "plan_remarks": "Advised MRI Brain and Neurology follow-up"
  }
}

Index Examinations

Request:

GET /api/v1/clinic_patients/17/derma_examinations

Response:

200 OK
Content-Type: application/json

[
  {
    "id": 2,
    "clinic_patient_id": 17,
    "doctor_id": 8,
    "clinic_id": 10,
    "event_id": 424,
    "event_type": "Appointment",
    "examination_site": "generalized",
    "lesion_type": "plaque",
    "lesion_color": "hyperpigmented",
    "lesion_configuration": "scattered",
    "surface": "scaly",
    "secondary_changes": "lichenification",
    "notes": "Chronic plaque psoriasis",
    "deleted": false,
    "created_at": "2025-11-14T06:15:22.123Z",
    "updated_at": "2025-11-14T06:15:22.123Z"
  },
  {
    "id": 1,
    "clinic_patient_id": 17,
    "doctor_id": 8,
    "clinic_id": 10,
    "event_id": 424,
    "event_type": "Appointment",
    "examination_site": "localized",
    "lesion_type": "papule",
    "lesion_color": "erythematous",
    "lesion_configuration": "grouped",
    "surface": "smooth",
    "secondary_changes": "scaly",
    "notes": "Patient presents with acne-like eruptions on the face.",
    "deleted": false,
    "created_at": "2025-11-14T05:58:14.416Z",
    "updated_at": "2025-11-14T05:58:14.416Z"
  }
]

Delete Examination

Request:

DELETE /api/v1/clinic_patients/17/derma_examinations/1

Response:

204 No Content

Error Handling

Validation Errors

{
  "errors": {
    "examination_type": "Could Not Be Saved: Examination site must be localized, generalized, or symmetrical, Lesion type must be macule, papule, vesicle, pustule, plaque, or nodule"
  }
}

Not Found Errors

{
  "errors": {
    "examination": "not found"
  }
}

Key Implementation Details

1. Event-Based Appointment Linking

All examinations support optional linking to appointments through:

  • event_id: Reference to appointment ID
  • event_type: Set to 'Appointment'
  • belongs_to :event, polymorphic: true

2. Comprehensive Validation

Each examination type has medical-specific validation rules based on clinical checklists:

  • Dermatology: Site, lesion type, color, configuration, surface, secondary changes
  • Neurology: Consciousness, orientation, speech, cranial nerves, motor/sensory systems, reflexes, gait, coordination
  • Cardiology: General physical, inspection, palpation, percussion, auscultation, additional findings

3. Soft Delete Implementation

  • Uses update_columns to bypass validations during delete
  • Manually triggers patient history logging
  • Supports audit trail with deleted_by_user_id and deleted_reason

4. Patient History Integration

  • Automatic logging on create/update via after_save callback
  • Manual logging on delete to ensure consistency
  • Structured data organization by examination type
  • Deletion status tracking in patient history

5. Error Handling

  • Detailed validation error messages with field descriptions
  • Consistent error response format across all examination types
  • Proper HTTP status codes for different error scenarios

Database Migrations

Key Migration Files

MigrationFilePurpose
CreateDermaExaminationsbackend/parts/patient/migrate/20251113000000_create_prescription_examinations.rbCreates derma_examinations table (renamed)
CreateNeuroExaminationsbackend/parts/patient/migrate/20251113075535_create_neuro_examinations.rbCreates neuro_examinations table
CreateCardioExaminationsbackend/parts/patient/migrate/20251113095527_create_cardio_examinations.rbCreates cardio_examinations table
RenameExaminationDataToDermaExaminationDatabackend/parts/patient/migrate/20251113071647_rename_examination_data_to_derma_examination_data.rbUpdates derma table structure

Security and Authorization

All controllers use Pundit policies for authorization:

before_action :authorize_action

def authorize_action
  authorize ExaminationType, "#{action_name}?"
end

Policies control access based on:

  • Doctor-clinic relationship
  • Patient assignment
  • User roles and permissions

This documentation covers the complete medical examination system implementation including dermatology, neurology, and cardiology examinations with comprehensive API endpoints, database schema, validation rules, and integration patterns.

On this page