core PK: id 15 required 1 unique

Description

Training and certification course offered to peer mentors, with prerequisite requirements, schedule, and seat capacity. Completing a course issues a certification; HLF uses certifications as an eligibility gate that auto-removes expired peer mentors from assignment pools.

21
Attributes
6
Indexes
10
Validation Rules
21
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key, generated server-side via gen_random_uuid()
PKrequiredunique
organization_id uuid Foreign key to organizations. Scopes the course to a specific member organization; only users affiliated with this org can enroll.
required
title string Human-readable course name shown in the catalog and detail screens (e.g., 'Likeperson grunnkurs 2025'). Maximum 255 characters.
required
description text Full-length course description covering learning outcomes, content overview, and any special requirements. Rendered as markdown in Course Detail Screen.
-
course_type enum Delivery modality of the course. Determines which schedule fields are mandatory and affects UI rendering.
required
prerequisites json Array of certification type identifiers that a peer mentor must hold before enrolling. Empty array means no prerequisites. Validated by CourseEnrollmentService at enrollment time. Example: ["peer-mentor-basic", "first-aid"].
required
schedule json Structured schedule object containing session details. Shape: { start_date: ISO-date, end_date: ISO-date, location: string | null, sessions: [{ date: ISO-date, start_time: string, end_time: string, location: string | null }] }. Required for in_person and hybrid types.
-
instructor_name string Name of the course instructor or facilitator, displayed on the Course Detail Screen. Optional for self-paced courses.
-
location string Primary venue or platform for the course (e.g., 'Oslo Kongressenter' or 'Zoom'). Redundant for structured schedule sessions but provides a quick summary for list views.
-
seats_total integer Maximum number of concurrent enrollments allowed. Must be a positive integer. A value of -1 may represent unlimited seats for self-paced courses.
required
seats_available integer Denormalized count of remaining open seats. Decremented on confirmed enrollment, incremented on withdrawal or cancellation. Enforced by database trigger to prevent negative values. Real-time updates streamed via Supabase Realtime.
required
enrollment_deadline datetime UTC timestamp after which new enrollments are rejected. Must be before the course start_date in the schedule. Displayed with countdown on Course Detail Screen.
-
certification_type string Identifier for the type of certification issued upon successful completion (e.g., 'peer-mentor-basic', 'hearing-aid-specialist'). Used by CertificateService to set the certification_type field on the resulting certifications record.
required
certification_validity_months integer Number of months the issued certification remains valid after completion. Drives expiry_date computation on the certifications record. Critical for HLF: expired certifications auto-remove peer mentors from active pools via the CertificateExpiryScheduler.
required
duration_hours decimal Total estimated learning time in hours. Used in catalog display and Bufdir reporting for training hours contributed by peer mentors.
-
is_active boolean Soft-delete / visibility flag. Inactive courses are hidden from Course Catalog Screen and block new enrollments. Existing enrollments on deactivated courses are preserved for certification issuance.
required
is_recurring boolean Indicates whether this course is offered on a recurring schedule. Recurring courses generate new schedule instances; enrollment_deadline and schedule are reset per instance by admin.
required
max_enrollments_per_user integer Maximum number of times a single user may enroll in this course across all time. Typically 1 for certification courses; may be higher for refresher or workshop-style courses.
required
created_by uuid User ID of the admin or coordinator who created the course record. Foreign key to users. Used in audit log display.
required
created_at datetime UTC timestamp of record creation, set server-side via now().
required
updated_at datetime UTC timestamp of last modification, updated via trigger on any field change.
required

Database Indexes

idx_courses_organization_id
btree

Columns: organization_id

idx_courses_organization_id_is_active
btree

Columns: organization_id, is_active

idx_courses_enrollment_deadline
btree

Columns: enrollment_deadline

idx_courses_certification_type
btree

Columns: certification_type

idx_courses_organization_id_certification_type
btree

Columns: organization_id, certification_type

idx_courses_is_active_enrollment_deadline
btree

Columns: is_active, enrollment_deadline

Validation Rules

title_not_empty error

Validation failed

seats_total_positive error

Validation failed

enrollment_deadline_before_start error

Validation failed

certification_validity_positive error

Validation failed

schedule_required_for_synchronous_types error

Validation failed

prerequisites_valid_certification_types error

Validation failed

organization_id_exists error

Validation failed

certification_type_format error

Validation failed

seats_available_lte_seats_total error

Validation failed

upcoming_deadline_warning warning

Validation failed

Business Rules

seat_capacity_enforcement
on_create

A new enrollment is rejected if seats_available equals 0 at the moment of the enrollment request. The check and the decrement of seats_available must occur within a single database transaction to prevent race-condition overbooking. This is enforced via a Supabase RPC call rather than a client-side check.

prerequisite_certification_check
on_create

Before confirming enrollment, CourseEnrollmentService queries the certifications table for the enrolling user and verifies that each certification_type listed in the course's prerequisites array exists and is not expired. Enrollment is blocked if any prerequisite is missing or expired.

enrollment_deadline_enforcement
on_create

Enrollment attempts received after enrollment_deadline are rejected with a deadline-passed error. The deadline is checked server-side in the enrollment RPC to prevent client clock manipulation.

certification_issuance_on_completion
on_update

When a course_enrollment record transitions to status 'completed', CertificateService automatically creates a certifications record for the user, setting issue_date to now() and expiry_date to now() + certification_validity_months. The certification_type on the new record is copied from the course.

hlf_expired_cert_auto_removal
always

For organizations with the HLF certification gate enabled, the CertificateExpiryScheduler runs a daily job: any peer mentor whose required course certification has expired has their peer_mentor_availability status automatically set to 'paused'. The coordinator is notified via push notification. This enforces HLF's policy that expired certifications remove peer mentors from active assignment pools.

organization_scope_isolation
always

Supabase RLS policies on the courses table restrict SELECT to users whose user_organization_memberships includes the course's organization_id. INSERT, UPDATE, and DELETE are restricted to users with admin or coordinator roles in that organization. Cross-organization course visibility is not permitted.

max_enrollment_per_user_limit
on_create

If max_enrollments_per_user is 1 (the default), a user may not enroll in the same course more than once. CourseEnrollmentService queries existing enrollment records before creating a new one and rejects the request with an 'already enrolled' error if the limit is reached.

inactive_course_blocks_enrollment
always

If is_active is false, the course is hidden from Course Catalog Screen and any direct enrollment attempt is rejected server-side. Existing enrollments and issued certifications are unaffected by deactivation.

seats_available_consistency
always

A database trigger maintains seats_available as seats_total minus the count of confirmed and completed course_enrollments. The trigger fires on INSERT, UPDATE, and DELETE of course_enrollments to keep the denormalized count consistent. seats_available may never be negative or exceed seats_total.

physical_card_parallel_system
always

For HLF, digital certification issuance does not replace the physical peer mentor card. The certifications record carries a physical_card_issued boolean flag that coordinators must manually confirm separately. The Course and Certificate screens surface both statuses simultaneously to coordinate parallel workflows.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage

Entity Relationships

certifications
incoming many_to_one

Each certification is issued upon successful completion of a specific course

optional
course_enrollments
outgoing one_to_many

A course may have multiple enrolled users up to its configured seat capacity

optional
organizations
outgoing many_to_one

Courses are offered by specific organizations and scoped for enrollment eligibility and certificate issuance

required