Course
Data Entity
Description
Represents a training course or certification program offered by an organization to peer mentors and coordinators. Supports HLF-style certification workflows including enrollment, completion tracking, expiry reminders, and digital certificate issuance. Also covers career workshop sessions (Blindeforbundet) and general training offerings.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key, globally unique course identifier | PKrequiredunique |
organization_id |
uuid |
FK to organizations. Courses are scoped to a single organization; peer mentors from other orgs cannot see or enroll. | required |
title |
string |
Human-readable course name shown in the course list and detail screens | required |
description |
text |
Full course description shown on the course detail screen, may include learning objectives and prerequisites | - |
course_type |
enum |
Categorizes the course format for filtering and UI display | required |
status |
enum |
Lifecycle state. Only 'published' courses accept new enrollments. | required |
max_participants |
integer |
Optional enrollment cap. NULL means unlimited. Enrollment is rejected once this count is reached. | - |
duration_hours |
decimal |
Expected total duration in hours. Used for display and Bufdir reporting context. | - |
start_date |
datetime |
Scheduled start of the course. NULL for self-paced or rolling-enrollment courses. | - |
end_date |
datetime |
Scheduled end of the course. Must be after start_date when both are set. | - |
enrollment_deadline |
datetime |
Last date/time a user may enroll. Must be on or before start_date when start_date is set. | - |
location |
string |
Physical address or venue name for in-person courses. May be 'Online' for virtual sessions. | - |
is_online |
boolean |
True for remote/video courses. When true, meeting_url is required. | required |
meeting_url |
string |
Video conference link (Zoom, Teams, etc.) shown to enrolled participants. Required when is_online is true. | - |
certificate_valid_months |
integer |
How long the issued certificate remains valid in months (e.g. 12 for one year). NULL means no expiry. Drives certificate_expiry_scheduler reminders. | - |
requires_prerequisite_course_id |
uuid |
Self-referencing FK. If set, users must have a completed enrollment in the referenced course before enrolling here. | - |
instructor_name |
string |
Name of the primary instructor or facilitator shown on the course detail screen | - |
instructor_contact |
string |
Email or phone of the instructor for participant questions | - |
issues_certificate |
boolean |
When true, completing this course triggers certificate generation and storage in the certifications table | required |
created_by_user_id |
uuid |
FK to users. Org Admin or Coordinator who created the course record. | required |
created_at |
datetime |
Timestamp when the record was first created | required |
updated_at |
datetime |
Timestamp of the most recent update, maintained automatically | required |
metadata |
json |
Extensible bag for org-specific fields (e.g. Blindeforbundet career workshop todo lists, HLF sertifisering tier). Validated against a loose schema at save time. | - |
Database Indexes
idx_courses_organization_id
Columns: organization_id
idx_courses_status
Columns: status
idx_courses_start_date
Columns: start_date
idx_courses_org_type_status
Columns: organization_id, course_type, status
idx_courses_prerequisite
Columns: requires_prerequisite_course_id
Validation Rules
title_not_empty
error
Validation failed
end_date_after_start_date
error
Validation failed
enrollment_deadline_before_start
error
Validation failed
meeting_url_required_when_online
error
Validation failed
max_participants_positive
error
Validation failed
certificate_valid_months_positive
error
Validation failed
no_self_referencing_prerequisite
error
Validation failed
duration_hours_positive
error
Validation failed
status_transition_guard
error
Validation failed
Business Rules
enrollment_requires_published_status
A user may only enroll in a course whose status is 'published'. Attempting to enroll in a draft, archived, or cancelled course must return an error. Admin operations (editing, archiving) bypass this check.
max_participants_cap
When max_participants is set, the total count of non-cancelled enrollments in course_enrollments must be strictly less than max_participants before a new enrollment is accepted. Race conditions are handled with a database-level row lock on the course record.
enrollment_deadline_enforced
If enrollment_deadline is set and the current timestamp is past that value, new enrollments are rejected even if max_participants is not reached.
prerequisite_completion_required
When requires_prerequisite_course_id is set, the enrolling user must have a course_enrollment record for that course with status 'completed'. The check is performed against the same organization.
certificate_issued_on_completion
When issues_certificate is true and a course_enrollment transitions to 'completed', course-enrollment-service triggers certificate-service to create a record in the certifications table. Certificate expiry is calculated as completed_at + certificate_valid_months.
organization_scoped_visibility
Courses are only visible and accessible to users (peer mentors, coordinators, org admins) belonging to the same organization. The RBAC middleware enforces the organization_id filter on every query.
cancellation_notifies_enrollees
When a course status transitions to 'cancelled', the scenario-engine-service triggers a push notification and email to all enrolled participants whose enrollment status is not already 'cancelled'.
certificate_expiry_reminder
certificate-expiry-scheduler runs daily and queries courses with issues_certificate=true and certificate_valid_months set. For each enrolled user whose certificate approaches expiry (30 days out), a push notification is dispatched.