Skip to content

Last updated:

Architecture Overview

The CPR (Clinical Patient Records) system is a multi-branch ophthalmic clinic management platform built with Laravel 12 serving as a RESTful API backend.

System Architecture

┌─────────────────────────────────────────────────────┐
│                   Frontend (SPA)                     │
│            Vue 3 + Inertia.js / API Client           │
└──────────────────────┬──────────────────────────────┘
                       │ HTTP / JSON
                       │ Authorization: Bearer <token>
                       │ X-Branch-Id: <branch_id>
┌──────────────────────▼──────────────────────────────┐
│                  Laravel 12 API                      │
│                                                      │
│  ┌─────────────┐  ┌──────────────┐  ┌────────────┐  │
│  │  Sanctum    │  │  Middleware   │  │  Rate      │  │
│  │  Auth       │  │  Branch Ctx  │  │  Limiting  │  │
│  └──────┬──────┘  └──────┬───────┘  └─────┬──────┘  │
│         │                │                 │         │
│  ┌──────▼────────────────▼─────────────────▼──────┐  │
│  │              Controllers (API v1)              │  │
│  └──────────────────────┬─────────────────────────┘  │
│                         │                            │
│  ┌──────────────────────▼─────────────────────────┐  │
│  │           Services (Business Logic)            │  │
│  │         Actions  │  Pipelines  │  DTOs         │  │
│  └──────────────────────┬─────────────────────────┘  │
│                         │                            │
│  ┌──────────────────────▼─────────────────────────┐  │
│  │        Repositories (Data Access Layer)         │  │
│  │         Contracts / Interfaces                  │  │
│  └──────────────────────┬─────────────────────────┘  │
│                         │                            │
│  ┌──────────────────────▼─────────────────────────┐  │
│  │        Eloquent Models + Resources              │  │
│  └──────────────────────┬─────────────────────────┘  │
│                         │                            │
└─────────────────────────┼────────────────────────────┘

              ┌───────────▼───────────┐
              │    MySQL 8.4 / SQLite │
              │    Redis 7 (cache)    │
              └───────────────────────┘

Technology Stack

LayerTechnologyVersion
FrameworkLaravel12.0
LanguagePHP8.2+
DatabaseMySQL (prod) / SQLite (dev)8.4
Cache & QueueRedis7
AuthLaravel Sanctum4.0
RBACSpatie Laravel Permission6.23
Audit LoggingSpatie Activity Log4.12
Error TrackingSentry4.20
API DocsDedoc Scramble0.13
TestingPest PHP4.1
Static AnalysisPHPStan (Larastan)3.0
ContainersDocker (Laravel Sail)-
Image ProcessingIntervention Image3.0

Design Patterns

The codebase follows a layered architecture with clear separation of concerns:

Repository Pattern

All data access is abstracted through repositories that implement contracts (interfaces). This decouples business logic from the database layer.

Controller → Service → Repository → Model → Database

Service Layer

Services orchestrate business logic and coordinate between repositories, actions, and pipelines. Controllers never access repositories directly.

Action Pattern

Single-responsibility command classes that encapsulate discrete operations (e.g., CreateBranchAction, ToggleMedicineStatusAction).

Pipeline Pattern

Sequential processing chains for complex workflows like patient creation and password resets. Each step is a class with a handle($data, Closure $next) method.

DTO Pattern

Data Transfer Objects carry validated data between layers, especially through pipelines.

Multi-Branch Architecture

The system supports multiple clinic branches with data isolation. Branch context is enforced via the EnsureBranchContext middleware, which resolves the branch from:

  1. X-Branch-Id HTTP header (primary)
  2. branch_id query parameter (fallback)
  3. User's default_branch_id (last resort)

Branch-scoped routes ensure that patients, visits, queues, and billing data are isolated per branch.

Key Modules

ModuleDescription
Patient ManagementRegistration, search, export, demographics, top-occupation analytics
Patient Duplicatespatient-duplicates:scan artisan command + admin UI for merge/dismiss
Patient VisitsVisit tracking, plans, follow-ups
Clinical Examinations14+ ophthalmic exam types (tonometry, refraction, slit lamp, biometry, indirect ophthalmoscopy + PRP, etc.)
Queue SystemService-based queue with tickets, transfers, priority types
Queue ReservationsPre-booking for a future date; daily capacity guard + scheduled no-show marking
BillingTransactions, bill items, payment methods, insurance
PharmacyInventory, stock tracking, purchase orders, deliveries
SurgeryScheduling, locations, doctor assignments
AdministrationBranches, roles, permissions, audit logging, database backups
Data MigrationLegacy MS Access importer, data-mappings UI, import history (three independent permissions)

Canonical reference data

A few patient fields store canonical codes rather than free text — translated via App\Support\* classes and the data-mappings layer at import time:

FieldStorageSource class
nationalityISO-like code, e.g. phl, phl-cebuanoApp\Support\Nationalities
occupationShort job code, e.g. ACC, ENGApp\Support\Occupations
civil_statusSingle character: S, M, W, D, A, PApp\Enums\PatientCivilStatusEnum

Pre-existing rows imported before 2026-05-25 may still hold raw adjectives or free text (no backfill). See memory: patient-demographic-storage.

Next Steps

CPR - Clinical Patient Records