Student Hold Form
Field reference for student registration holds.
Hold Type Definition
| Field | Type | Required | Max Length | Validation | Notes |
|---|---|---|---|---|---|
| Hold Type ID | Integer | Auto | - | - | System-generated identifier |
| Hold Type Code | Text | Yes | 50 | Unique | Hold type code (e.g., ADVISOR, FINANCIAL) |
| Name | Text | Yes | 200 | - | Display name |
| Description | Text Area | No | 1000 | - | Detailed description |
| Enforcement Level | Select | Yes | - | BLOCK_ALL, BLOCK_COMPLETION, INFORMATIONAL | What the hold blocks. The only field that gates registration |
| Category | Select | Yes | 20 | see below | Descriptive grouping; nothing enforces off it |
Enforcement Levels
| Code | Label | Planning | Waitlist | Register |
|---|---|---|---|---|
| BLOCK_ALL | Blocks everything | No | No | No |
| BLOCK_COMPLETION | Blocks completion | Yes | Yes | No |
| INFORMATIONAL | Informational | Yes | Yes | Yes |
The levels form a ladder: BLOCK_ALL refuses everything BLOCK_COMPLETION refuses, and more. Enforced by enforceHolds in internal/domain/registration/hold_gate.go, called from every write path that creates a plan, a waitlist entry or an enrollment.
Migration 177 added the column with a CHECK constraint. It replaced a single prevents_registration boolean derived from the code prefix by the ODS importer, which is why library-balance holds used to block registration.
Category Values
Grouping for filtering and reporting only: FINANCIAL, HEALTH, REGISTRATION, HOUSING, ADMISSIONS, ACADEMIC, DISCIPLINARY, OTHER. CHECK-constrained since migration 177.
Before 177 this column carried two incompatible vocabularies at once — BLOCKING/COMPLETING on seven hand-seeded rows, domain names on the 36 imported from Colleague — with no constraint, and the UI coloured its badges off it. That is why imported holds all rendered as mild advisories.
Hold Type Independent Flags
| Field | Type | Required | Notes |
|---|---|---|---|
| Prevents Transcript | Boolean | No | Withholds transcripts. Orthogonal to enforcement level |
| Prevents Graduation | Boolean | No | Blocks graduation applications. Enforced in domain/audit |
| Student Visible | Boolean | No | False hides the hold from the student; staff always see it. From Colleague REST_PRTL_DISPLAY_FLAG |
| Default Severity | Smallint | No | Colleague REST_SEVERITY, reference only |
Hold Type Role Lists
Stored in records.hold_type_roles, one row per (hold type, role code) with can_place and can_clear booleans. Shaped after records.workflow_step_permissions.
| Field | Type | Notes |
|---|---|---|
| Place Roles | Multi-select (role codes) | Roles that may place this hold |
| Clear Roles | Multi-select (role codes) | Roles that may clear this hold |
Checked against the caller's active role, not the union of roles held. An empty list means superuser-only — deliberate fail-closed behaviour.
Replaced the single-FK create_role_id / clear_role_id columns, which were stored and displayed but never consulted by any code path.
Hold Type Administrative Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| Resolution Instructions | Text Area | No | Default student-facing message. Imported from Colleague REST_PRTL_DISPLAY_DESC_DTL, sanitized to a small HTML allowlist |
| Contact Office | Text | No | Office to contact. Parsed from the Colleague instruction text |
| Contact Email | No | Email for resolution | |
| Contact Phone | Text | No | Phone for resolution |
| Is Active | Boolean | No | Hold type is in use. Set false by the import for restrictions Colleague has retired |
| Sort Order | Integer | No | Display order |
| Auto Create Query | Text Area | No | Not implemented. Stored, never evaluated |
| Auto Clear Query | Text Area | No | Not implemented. Stored, never evaluated |
| Auto Clear Script | Text | No | Not implemented. Stored, never evaluated |
Student Hold Record
| Field | Type | Required | Max Length | Validation | Notes |
|---|---|---|---|---|---|
| Student Hold ID | UUID | Auto | - | - | System-generated identifier |
| Student | Select (FK) | Yes | - | Must exist | Student with hold |
| Hold Type | Select (FK) | Yes | - | Must exist | Type of hold |
| Term | Select (FK) | No | - | Must exist | Term-specific hold. Null means every term, which is what all imported holds are — Colleague restrictions carry no term |
| Reason | Text Area | No | 1000 | - | Internal note. Never shown to the student |
| Custom Message | Text Area | No | - | - | Student-facing text for this hold, overriding the hold type's resolution instructions. Sanitized on save |
| Severity | Smallint | No | - | - | Colleague STR_SEVERITY for this hold |
| Expiration Date | Date | No | - | Future date | Auto-expire date. Applied at query time as well as by the flag |
| Is Active | Boolean | Yes | - | - | Hold is currently active |
A hold counts as in force when is_active is true and the expiration date is absent or not yet passed. Nothing sweeps expired holds, so the date is checked in the query rather than trusted to a background job.
The API returns a resolved student_message alongside these: the custom message if set, otherwise the hold type's resolution instructions. Clients should render that rather than implementing the fallback themselves.
Hold Creation Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| Created By Person | Select (FK) | Conditional | Person who created hold |
| Created By System | Boolean | No | Created automatically |
| Created At | DateTime | Auto | When hold was created |
Hold Clearing Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| Cleared By Person | Select (FK) | Conditional | Person who cleared hold |
| Cleared By System | Boolean | No | Cleared automatically |
| Cleared At | DateTime | No | When hold was cleared |
| Clear Reason | Text Area | No | Reason for clearing |
Hold Types in Use
Hold types are not hand-authored: the nightly import creates one per Colleague restriction code. The codes below are the ones seen on students enrolled in current terms; the full set is 36, of which 12 are marked retired in Colleague.
| Code | Colleague description | Owning office |
|---|---|---|
| FA001 | FA-Financial Clearance Needed | Student Financial Services |
| HS001 | HS-Need Health Clearance | Health Services |
| RGTRN | High School Transcript | Enrollment |
| FIADV | Academic Advisor Meeting | (advisor) |
| SSCPB | Academic Probation | Student Success Center |
| SSIS | SS-International Students | Student & Spiritual Life |
| FASUM | FA-Summer Clearance Needed | Student Financial Services |
| SSHOU | Housing | Student & Spiritual Life |
| AMCMT | Pioneers Commitment Form | Admissions |
| LCTRA | Transcripts - Loans/Collection | Registrar and Records |
| RGMW | Medical Withdrawal | Registrar and Records |
| SSCTD | SS-Dismissal - Student Life | Student & Spiritual Life |
| SSCTZ | SS-Student Life Issues | Student & Spiritual Life |
| TIXCK | Title IX Check | Title IX |
| SSTIX | Title IX Training Required | Student & Spiritual Life |
Names come from cleanUp.dbo.RESTRICTIONS and are refreshed nightly. Enforcement level and role lists are local and are never overwritten by the import.
Computed Fields (Read-Only)
| Field | Description |
|---|---|
| Student Number | From student record |
| Student Name | From person record |
| Hold Type Name | From hold type |
| Enforcement Display | Human label for the enforcement level |
| Student Message | Custom message, else the hold type's resolution instructions |
| Days Active | Days since creation |
| Status Display | ACTIVE or CLEARED |
Validation Rules
- Student must exist
- Hold Type must be active
- Only one active hold per student per hold type (unless term-specific)
- Cleared By Person required if cleared manually
- Created By Person required if created manually
- Expiration Date should be in the future when set
Automation
The nightly Colleague import is the only thing that creates and removes holds automatically (internal/migration/daily/holds.go):
| Event | Action |
|---|---|
| Colleague applies a restriction | Hold created |
| Colleague releases a restriction | Hold removed |
| Colleague restriction deleted | Hold removed (delete-reconcile pass) |
| Expiration date passes | Hold stops being in force at query time |
The import only reads restrictions currently in force. A hold cleared by hand in SIS is re-activated on the next run if Colleague still shows the restriction — release it in Colleague, not here.
The query-driven auto-evaluation described by auto_create_query, auto_clear_query and auto_clear_script does not exist. The fields are stored and never read, records.hold_evaluation_log has never held a row, and POST /registration/hold-types/{id}/run_auto_create returns 501 Not Implemented.
Related Screens
- Student - Student record
- Enrollment - Affected registrations