ClinicFlow’s domain layer is built around a small set of clearly bounded entities and a rich set of immutable value objects. Every entity extendsDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/0Crazy-0/ClinicFlow/llms.txt
Use this file to discover all available pages before exploring further.
BaseEntity, which supplies a Guid Id, a domain-event queue (AddDomainEvent / ClearDomainEvents), and audit infrastructure. Entities that support soft-deletion additionally extend SoftDeletableEntity, which exposes an IsDeleted flag managed through MarkAsDeleted() and UndoDeletion().
Entities
The table below summarises every entity, its most important properties, and the lifecycle methods that enforce domain invariants.| Entity | Key Properties | Key Methods |
|---|---|---|
User | Role, Email, PhoneNumber, PasswordHash, IsActive, IsPhoneVerified, FailedLoginAttempts, LockoutEnd | Create, MarkPhoneAsVerified, RecordLogin, RecordFailedLogin, ChangePassword, Deactivate, Reactivate |
Doctor | UserId, FullName, MedicalSpecialtyId, LicenseNumber, Biography, ConsultationRoom | Create, UpdateProfile, Suspend, Reactivate |
Patient | UserId, FullName, RelationshipToUser, DateOfBirth, BloodType, Allergies, ChronicConditions, EmergencyContact | CreateSelf, CreateFamilyMember, UpdateMedicalProfile, UpdateEmergencyContact, EnsureCompleteProfile, GetAge, CloseAccount, RemoveFamilyMember |
Appointment | PatientId, DoctorId, AppointmentTypeId, ScheduledDate, TimeRange, Status, PatientNotes, ReceptionistNotes, RescheduleCount, CancellationReason | Schedule (factory), Reschedule, Cancel, CancelLate, CheckIn, Start, Complete, MarkAsRequiresReassignment, Reassign, CancelDueToSystemTimeout, MarkAsNoShowByStaff, MarkAsNoShowByDoctor |
Schedule | DoctorId, DayOfWeek, TimeRange, IsActive | Create, Deactivate, CoversTimeRange, EnsureNoDuplicateDay |
AppointmentTypeDefinition | Category, Name, Description, Duration, AgePolicy, IsUnrestrictedBySpecialty, AllowedSpecialtyIds, RequiredTemplates | Create, UpdateDetails, RestrictToSpecialties, MakeUnrestricted, AddAllowedSpecialty, RemoveAllowedSpecialty, ChangeAgePolicy, AddRequiredTemplate, RemoveRequiredTemplate, ValidatePatientEligibility, Deactivate, Reactivate |
MedicalRecord | PatientId, DoctorId, AppointmentId, ChiefComplaint, ClinicalDetails | Create, AddClinicalDetail |
PatientPenalty | PatientId, AppointmentId (nullable), Type, Reason, BlockedUntil (nullable), IsRemoved | CreateAutomaticWarning, CreateAutomaticBlock, CreateManualBlock, Remove |
ClinicalFormTemplate | Code, Name, Description, JsonSchemaDefinition | Create, UpdateDetails, UpdateSchema, Deactivate, Reactivate |
MedicalSpecialty | Name, Description, TypicalDuration, CancellationPolicy | Create, UpdateDetails, Deactivate, Reactivate, IsCancellationAllowed |
User
User represents an authentication account. It holds credentials, contact details, and a UserRole. The account tracks failed login attempts and enforces a 15-minute lockout after five consecutive failures (MaxFailedLoginAttempts = 5). Phone verification is a hard gate for patient-initiated scheduling.
Doctor
Doctor is linked 1-to-1 with a User account and belongs to a MedicalSpecialty. It holds a MedicalLicenseNumber and a ConsultationRoom. Calling Suspend() soft-deletes the doctor and raises a DoctorSuspendedEvent that automatically flags all future scheduled appointments as RequiresReassignment.
Patient
Patient represents a person receiving care. A user account may own multiple patient profiles — one Self profile and any number of family-member profiles (Child, Spouse, Parent, Sibling, Other). The domain enforces that BloodType and EmergencyContact must be present before the patient can book (EnsureCompleteProfile). GetAge(referenceDate) computes the patient’s age on any given date for eligibility checks.
Appointment
Appointment is the central aggregate. It is created exclusively through the Appointment.Schedule(...) internal factory and transitions through a well-defined status machine (see Status Lifecycle below). The domain limits rescheduling to one occurrence per appointment (RescheduleCount >= 1 throws).
Schedule
Schedule defines a recurring weekly availability slot for a doctor on a given DayOfWeek. Availability is checked via CoversTimeRange(requested), which returns true only when the slot is active and its TimeRange fully contains the requested time window.
AppointmentTypeDefinition
AppointmentTypeDefinition configures the clinical rules for a kind of appointment: category, expected duration, specialty restrictions, age eligibility, and required clinical form templates. It can be scoped to specific specialties via AllowedSpecialtyIds or set as globally unrestricted.
MedicalRecord
MedicalRecord is created when a doctor opens an encounter and captures the ChiefComplaint plus a collection of typed IClinicalDetailRecord entries (e.g., cardiology flags, dental odontograms). Each template code may appear at most once per record.
PatientPenalty
PatientPenalty records a single disciplinary event against a patient — either a Warning or a TemporaryBlock. Automatic warnings always link to an AppointmentId; manual blocks do not. Staff can call Remove() to set IsRemoved = true, which excludes the penalty from all active-block checks.
ClinicalFormTemplate
ClinicalFormTemplate defines a dynamic JSON-schema-backed form. It carries an immutable Code (the natural key used by external systems and historical records) alongside a mutable Name, Description, and JsonSchemaDefinition.
MedicalSpecialty
MedicalSpecialty groups doctors by discipline and owns the cancellation policy for its appointments via a CancellationLimit value object. TypicalDuration is a statistical reference — the binding duration for scheduling comes from AppointmentTypeDefinition.Duration.
Value Objects
Value objects are C#record types — structurally equal, immutable after creation, and validated in their factory methods.
TimeRange
Wraps a
TimeOnly Start and TimeOnly End. Provides OverlapsWith(other) and Covers(other). Creation fails if Start >= End.AgeEligibilityPolicy
Holds optional
MinimumAge, MaximumAge (0–120), and a RequiresLegalGuardian flag. ValidatePatientEligibility(age, hasGuardianConsent) throws typed domain errors for out-of-range ages or missing guardian consent for patients under 18.PenaltyHistory
Wraps a
IReadOnlyList<PatientPenalty>. Exposes HasPriorWarnings, TotalHistoricalBlocks, IsCurrentlyBlocked(date), DetermineNextBlockDuration(), and EnsureNotBlocked(date).SchedulingClearance
A token record with no data properties. Created only by
SchedulingClearance.Granted(), which is called exclusively by IRegionalSchedulingService. Passing it to a scheduling service proves regulations have been evaluated.CancellationLimit
Defines the minimum notice window (in hours) for a penalty-free cancellation. Only pre-approved values are valid:
0, 12, 24, 48, 72. Created via CancellationLimit.FromHours(int).BloodType
Wraps a validated ABO/Rh string (
A+, A-, B+, B-, AB+, AB-, O+, O-). Normalised to upper-case on creation.PersonName
Enforces a 2–100 character trimmed full-name string.
EmailAddress
Normalised to lower-case, max 254 chars, validated with a regex pattern
^[^@\s]+@[^@\s]+\.[^@\s]+$.PhoneNumber
7–20 characters, validated with a permissive international phone regex. Accepts
+, dashes, spaces, and parentheses.MedicalLicenseNumber
4–15 character alphanumeric string. Acts as the doctor’s verifiable credential in the system.
ConsultationRoom
Compound value:
Number (1–35), Name (non-empty string), Floor (1–8). Renders as "Room {Number} - {Name} (Floor {Floor})".EmergencyContact
Composes a
PersonName and a PhoneNumber. Both sub-values are validated on creation.EncounterDuration
An integer
Minutes value constrained to 10–90 minutes in 5-minute increments. Created via EncounterDuration.FromMinutes(int).Enumerations
AppointmentStatus
Represents the full lifecycle of an appointment.| Value | Int | Description |
|---|---|---|
Scheduled | 1 | Booked and awaiting the visit date |
InProgress | 3 | The doctor has started the consultation |
Completed | 4 | The encounter has been closed |
Cancelled | 5 | Cancelled within the allowed window — no penalty |
NoShow | 6 | Patient did not attend |
LateCancellation | 7 | Cancelled after the notice deadline — triggers a penalty |
CheckedIn | 8 | Patient has arrived and checked in at the front desk |
RequiresReassignment | 9 | Doctor was suspended; appointment awaits a new doctor |
AppointmentCategory
| Value | Description |
|---|---|
FirstConsultation | Initial visit with a new patient |
FollowUp | Return visit to review a previous diagnosis or treatment |
Emergency | Urgent, unscheduled visit requiring immediate attention |
Checkup | Routine preventive health examination |
Procedure | Medical or surgical procedure |
Patients cannot cancel
Procedure appointments. Staff or doctors must handle those. Emergency appointments can only be cancelled by the patient themselves or by a parent if the patient is under 18.UserRole
| Value | Description |
|---|---|
Patient | Can book and manage their own appointments |
Doctor | Can schedule, reschedule, start, and complete encounters |
Receptionist | Front-desk staff with scheduling and administrative access |
Admin | Full system access |
PatientRelationship
Defines how a patient profile relates to the owning user account:Self, Child, Spouse, Parent, Sibling, Other. A Self patient is the primary profile and is the only relationship that can close an account.