# Model: Doctor

**Table**: `clinic_doctors` (new) · **Guard**: `doctor` (new) — mirrors `App\Models\HR\Employee\Employee`

## Purpose

A doctor's account and professional profile. Doctors log into their own portal (new `doctor`
guard, see `00-overview.md`), independent of the `admin` guard used by ERP staff and Clinic
Admins. A doctor can be linked to more than one branch (via `clinic_doctor_branch`), each with
its own price and schedule.

## Fields

| Column | Type | Constraints | Notes |
|---|---|---|---|
| `id` | bigint | PK | |
| `name` | string | | |
| `email` | string | unique | login identifier, same pattern as `hr_employees` |
| `password` | string | nullable initially, mirrors how `hr_employees` got `password` added via a later migration for portal auth | |
| `remember_token` | string | nullable | |
| `phone` | string | | |
| `photo_path` | string | nullable | |
| `specialty_id` | bigint | `foreignId('specialty_id')->constrained('clinic_specialties')->restrictOnDelete()` | one specialty per doctor |
| `bio` | text | nullable | |
| `qualifications` | text | nullable | |
| `years_experience` | unsignedTinyInteger | nullable | |
| `hr_employee_id` | bigint | `foreignId('hr_employee_id')->nullable()->constrained('hr_employees')->nullOnDelete()` | optional link if the doctor is *also* a payroll HR employee of the organization — not required |
| `status` | string | default `'active'` | `active` / `disabled` |
| `created_by` | bigint | `foreignId(...)->nullable()->constrained('admins')->nullOnDelete()` | which Clinic Admin/Super Admin added them |
| `created_at` / `updated_at` | timestamp | | |

**No `updated_by`/soft-deletes by default**, matching the "master tables get soft-deletes via a
separate later migration, not by default" convention — revisit if doctor records need soft
deletion once real usage patterns are known.

## Relationships

| Relation | Type | Target |
|---|---|---|
| `specialty()` | `belongsTo` | `Specialty` |
| `branches()` | `belongsToMany` (through `clinic_doctor_branch`) | `Core\Branch`, pivot columns `visit_price`, `consultation_price`, `slot_duration_minutes`, `is_active` |
| `schedules()` | `hasMany` | `DoctorSchedule` |
| `bookings()` | `hasMany` | `Booking` |
| `medicalRecords()` | `hasMany` | `MedicalRecord` |
| `chatMessages()` | polymorphic, see `ChatMessage.md` | `ChatMessage` |
| `hrEmployee()` | `belongsTo` (nullable) | `HR\Employee\Employee` |

## Decisions

- `extends Illuminate\Foundation\Auth\User as Authenticatable`, exactly like
  `App\Models\HR\Employee\Employee` (`app/Models/HR/Employee/Employee.php:18`) — not a trait, the
  base class.
- New guard `doctor` / provider `clinic_doctors` in `config/auth.php`, mirroring `employee` /
  `employees` exactly.
- Cannot edit their own `clinic_doctor_branch.visit_price` / `.consultation_price` — enforced in
  `Doctor\*` controllers (no update route for those fields on that guard) unless Super Admin
  later opts to allow it (per the brief: "Doctor sees the price but can't change it unless Super
  Admin allows").
