ADocumentation 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.
MedicalRecord is the permanent, structured output of a clinical encounter. It ties together the patient, the attending doctor, and the appointment, and it holds an ordered collection of IClinicalDetailRecord entries — each a JSON payload validated against a ClinicalFormTemplate schema. Records are created and completed atomically through MedicalEncounterService, which also advances the appointment lifecycle.
The MedicalRecord Entity
| Field | Type | Notes |
|---|---|---|
PatientId | Guid | Links to the Patient aggregate |
DoctorId | Guid | Links to the Doctor aggregate |
AppointmentId | Guid | One record per appointment; enforced by repository |
ChiefComplaint | string | Required; patient-reported chief symptom |
ClinicalDetails | IReadOnlyCollection<IClinicalDetailRecord> | Structured form data collected during the encounter |
AddClinicalDetail Uniqueness Check
MedicalRecord.AddClinicalDetail enforces that each TemplateCode appears at most once in the record. Attempting to add a second entry with the same code throws DetailAlreadyExists:
MedicalRecord.Create is internal — the only authorised caller is MedicalEncounterService.InitiateMedicalRecord.
Dynamic Clinical Detail Pattern
Clinical details use a two-type pattern: a domain interface that describes the contract, and a concrete EF Core–mapped entity that stores it.IClinicalDetailRecord
DynamicClinicalDetail
DynamicClinicalDetail is the concrete implementation persisted to the database. It stores any template’s data as a raw JSON string, keeping the domain free of speciality-specific types.
DynamicClinicalDetail is validated against the JsonSchemaDefinition of the matching ClinicalFormTemplate before it is appended to the record.
MedicalEncounterService
MedicalEncounterService is the domain service that orchestrates the entire encounter lifecycle. It is an instance service (not static) that accepts IEnumerable<IMedicalRecordValidationPolicy> and IJsonSchemaValidator through constructor injection. It exposes three entry points:
InitiateMedicalRecord (static)
Creates a
MedicalRecord shell from an in-progress appointment. Throws AppointmentNotInProgress if the appointment is not in InProgress status.ValidateAndCompleteRecord (instance)
Runs all registered
IMedicalRecordValidationPolicy instances (e.g., the required-template policy), appends every provided IClinicalDetailRecord to the record, and calls Appointment.Complete(completedAt).AppendClinicalDetail (instance)
Used by
AddClinicalDetailToMedicalRecord to add a single detail to an existing record. Validates that TemplateCode matches the template, that the payload is non-empty, and then validates the JSON payload against the template’s JsonSchemaDefinition via IJsonSchemaValidator before calling AddClinicalDetail.The
MedicalRecord is created atomically with the appointment completion inside a single Unit of Work transaction. CompleteMedicalEncounterCommandHandler calls both InitiateMedicalRecord and ValidateAndCompleteRecord and then persists everything in a single SaveChangesAsync call, ensuring no partially completed encounter is ever stored.Template Validation
Clinical details are validated against theRequiredTemplates collection defined on the AppointmentTypeDefinition. At least one registered IMedicalRecordValidationPolicy (the built-in MetadataFormValidationPolicy) enforces that every required template has a matching IClinicalDetailRecord in the provided details list. Any missing template raises a validation error before the record is saved.
Commands
CompleteMedicalEncounter
The primary write command. Creates theMedicalRecord and completes the appointment in one transaction.
Guid — the new MedicalRecord.Id.
Handler flow:
- Loads
Doctor,Appointment, andAppointmentTypeDefinition. - Builds a list of
DynamicClinicalDetailfromDetails. - Calls
MedicalEncounterService.InitiateMedicalRecord→ thenValidateAndCompleteRecord. - Persists
MedicalRecordand the updatedAppointmentin oneSaveChangesAsync.
AddClinicalDetailToMedicalRecord
Adds a single structured detail to an existing record. This is useful when a doctor needs to attach a supplementary form (e.g., lab results) after the initial encounter record is created but before it is formally closed.MedicalRecord and the ClinicalFormTemplate by TemplateCode, creates a DynamicClinicalDetail, and delegates to MedicalEncounterService.AppendClinicalDetail for schema validation before saving.
Immutability After Completion
OnceAppointment.Complete has been called, the appointment transitions to Completed status and can no longer be moved back to InProgress. Because MedicalRecord.Create requires AppointmentStatus.InProgress, and the repository enforces a one-record-per-appointment constraint, it is impossible to create a second record or reopen a completed one.
Queries
GetMedicalRecordByAppointmentId
Returns a single
MedicalRecordDto for the given appointment.GetMedicalRecordsByPatientId
Paginated history for a patient — ordered by appointment date.
GetMedicalRecordsByDoctorId
Paginated encounter history authored by a specific doctor.
GetClinicalDetailByTemplateCode
Fetches a single
ClinicalDetailDto from a record by its TemplateCode. Useful for rendering a specific form’s data in the UI.