The Penalties module enforces booking-eligibility rules by recording warnings and temporary blocks against patient profiles. Penalties are created in two ways: automatically by the domain when a patient no-shows or cancels too late, and manually by clinic staff using theDocumentation 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.
BlockPatient command. Manual blocks always result in a TemporaryBlock penalty with a staff-defined duration. Automatic warnings and blocks are created internally by domain event handlers and are not exposed as commands.
Automatic penalties (warnings for late cancellations, blocks for repeat no-shows) are raised by domain event handlers that react to
AppointmentMarkedAsNoShowEvent and AppointmentLateCancelledEvent. These internal penalty records share the same PatientPenalty entity and DTO as manual blocks, and appear in all penalty query results. The AppointmentId field on the DTO is non-null for automatic penalties and null for manual blocks.BlockDuration Enum
BlockDuration specifies the predefined duration in calendar days for a manual block.
| Value | Days | Use case |
|---|---|---|
Minor | 5 | First or minor infraction |
Moderate | 15 | Repeated or moderately serious behaviour |
Severe | 30 | Persistent non-compliance |
BlockedUntil date is computed as today + (int)BlockDuration using TimeProvider.GetUtcNow().
PenaltyType Enum
Warning does not prevent booking; it is advisory only. A TemporaryBlock prevents the patient from booking new appointments until the BlockedUntil date has passed or the penalty is manually removed.
Commands
BlockPatient
Type:IRequest<Guid>
Manually creates a TemporaryBlock penalty for a patient. The handler calls PatientPenalty.CreateManualBlock, which sets Type = TemporaryBlock and calculates BlockedUntil = today + (int)duration in UTC. No appointment ID is associated with manual blocks.
Parameters
The patient to block. Must be a non-empty GUID. The patient does not need to be unblocked to receive a new block — multiple active block records can co-exist.
A free-text justification for the block, visible to staff in audit queries. Must not be empty.
The predefined block duration. Must be a valid
BlockDuration enum member (Minor, Moderate, or Severe).PatientPenalty.Id as a Guid.
RemovePenalty
Type:IRequest (returns Unit)
Marks an existing penalty (warning or block) as removed. Removed penalties are excluded from all active-block eligibility checks, effectively restoring the patient’s booking rights immediately if no other active block exists. Calling Remove() on an already-removed penalty throws DomainValidationException with DomainErrors.Penalty.AlreadyRemoved.
Parameters
The primary key of the penalty record to remove. Must be a non-empty GUID. Throws
EntityNotFoundException if not found.Unit (void).
Queries
GetPenaltiesByPatientId
Type:IRequest<PaginatedList<PatientPenaltyDto>>
Returns a paginated history of all penalties — active, expired, and removed — for a specific patient. Useful for auditing a patient’s full penalty timeline.
Parameters
The patient whose penalties to retrieve. Must be a non-empty GUID.
1-based page index. Must be ≥ 1.
Records per page. Must be between 1 and 100 (inclusive).
PaginatedList<PatientPenaltyDto> containing the complete penalty history for the patient.
GetActiveWarnings
Type:IRequest<PaginatedList<PatientPenaltyDto>>
Returns a paginated list of all active (non-removed) Warning penalties across all patients. An active warning has Type = Warning and IsRemoved = false.
Parameters
1-based page index. Must be ≥ 1.
Records per page. Must be between 1 and 100 (inclusive).
PaginatedList<PatientPenaltyDto> of all active warnings.
GetActiveBlockedPatients
Type:IRequest<PaginatedList<PatientPenaltyDto>>
Returns a paginated list of all TemporaryBlock penalties that are currently in effect — meaning Type = TemporaryBlock, IsRemoved = false, and BlockedUntil >= today.
Parameters
1-based page index. Must be ≥ 1.
Records per page. Must be between 1 and 100 (inclusive).
PaginatedList<PatientPenaltyDto> of all currently active temporary blocks.
Response Shape
PatientPenaltyDto
The unique identifier of this penalty record.
The patient this penalty is applied to.
The appointment that triggered the penalty. Populated for automatic penalties (e.g. no-show, late cancellation);
null for manual blocks created via BlockPatient.The penalty type as a string. One of
"Warning" or "TemporaryBlock" (mapped from PenaltyType enum).The human-readable reason for the penalty — either a system-generated message for automatic penalties or the staff-provided text for manual blocks.
The expiry date of a
TemporaryBlock penalty. null for Warning type penalties. Computed as issueDate + (int)BlockDuration in UTC days.true if the penalty has been cleared by staff via RemovePenalty; false while the penalty is active.