DegreeCourse json   -- for which degree programmes this course is appropriate for
    course       CourseId
    degree       StudyDegreeId
    terms        StudyTermsId
    UniqueDegreeCourse course degree terms
    deriving Generic
Course    -- Information about a single course; contained info is always visible to all users
    name             CourseName
    description      StoredMarkup Maybe    -- user-defined large Html, ought to contain module description
    linkExternal     URI Maybe     -- arbitrary user-defined url for external course page
    shorthand        (CI Text)     -- practical shorthand of course name, used for identification
    term             TermId        -- semester this course is taught
    school           SchoolId
    capacity         Int Maybe   -- number of allowed enrolements, if restricted
    -- canRegisterNow = maybe False (<= currentTime) registerFrom && maybe True (>= currentTime) registerTo
    visibleFrom      UTCTime Maybe default=now() -- course may be visible from a given day onwards or always hidden
    visibleTo        UTCTime Maybe -- course may be hidden from a given date onwards
    registerFrom     UTCTime Maybe -- enrolement allowed from a given day onwwards or prohibited
    registerTo       UTCTime Maybe -- enrolement may be prohibited from a given date onwards
    deregisterUntil  UTCTime Maybe -- unenrolement may be prohibited from a given date onwards
    deregisterNoShow Bool default=false
    registerSecret   Text Maybe    -- enrolement maybe protected by a simple common passphrase
    materialFree     Bool          -- False: only enrolled users may see course materials not stored in this table
    applicationsRequired       Bool default=false
    applicationsInstructions   StoredMarkup Maybe
    applicationsText           Bool default=false
    applicationsFiles          UploadMode "default='{\"mode\": \"no-upload\"}'::jsonb"
    applicationsRatingsVisible Bool default=false
    TermSchoolCourseShort  term school shorthand    -- shorthand must be unique within school and semester
    TermSchoolCourseName   term school name         -- name must be unique within school and semester
    deriving Generic

CourseScheduleOpt    -- opt-in/-out for displaying occurrence related to this course (may be overriden by specific occurrence opts)
    course CourseId
    user UserId
    opt Bool
    UniqueCourseScheduleOpt course user
    deriving Generic

CourseEvent
    type CourseEventType
    course CourseId
    room RoomReference Maybe
    roomHidden Bool default=false
    time Occurrences
    note StoredMarkup Maybe
    lastChanged UTCTime default=now()
    deriving Generic
CourseEventScheduleOpt                 -- opt-in/-out for course event display in a user's schedule (TODO: currently for all occurrences of a course event; separate opt-ins/-outs per occurrence in CourseEventTime instead?)
    courseEvent CourseEventId
    user UserId
    opt Bool                           -- whether the course event should be displayed; False <=> opt-out, True <=> opt-in
    UniqueCourseEventScheduleOpt courseEvent user
    deriving Generic

CourseAppInstructionFile
    course   CourseId
    title    FilePath
    content  FileContentReference Maybe
    modified UTCTime
    UniqueCourseAppInstructionFile course title
    deriving Generic

CourseEdit                -- who edited when a row in table "Course", kept indefinitely (might be replaced by generic Audit Table; like all ...-Edit tables)
    user         UserId
    time         UTCTime
    course       CourseId
    deriving Generic
Lecturer                       -- course ownership
    user         UserId
    course       CourseId
    type         LecturerType  default='"lecturer"'::jsonb
    UniqueLecturer user course -- note: multiple lecturers per course are allowed, but no duplicated rows in this table
    deriving Generic
CourseParticipant                      -- course enrolement
    course       CourseId
    user         UserId
    registration UTCTime               -- time of last enrolement for this course
    field        StudyFeaturesId Maybe MigrationOnly
    allocated    AllocationId Maybe    -- participant was centrally allocated
    state        CourseParticipantState
    UniqueParticipant user course
    deriving Eq Ord Show Generic
-- Replace the last two by the following, once an audit log is available
-- CourseUserNote                 -- lecturers of a specific course may share a text note on each enrolled student
--     course       CourseId
--     user         UserId
--     note         Html          -- arbitrary user-defined text; visible only to lecturer of this course
--     time         UTCTime       -- PROBLEM: deleted note has no modification date
--     editor       UserId        -- who edited this note last
--     UniqueCourseUserNote user course
CourseUserNote                 -- lecturers of a specific course may share a text note on each enrolled student
    course       CourseId
    user         UserId
    note         StoredMarkup  -- arbitrary user-defined text; visible only to lecturer of this course
    UniqueCourseUserNote user course
    deriving Generic
CourseUserNoteEdit             -- who edited a participants course note when
    user         UserId
    time         UTCTime
    note         CourseUserNoteId -- PROBLEM: deleted notes have no modification date any more
    deriving Generic

CourseUserExamOfficeOptOut
    course       CourseId
    user         UserId
    school       SchoolId
    UniqueCourseUserExamOfficeOptOut course user school
    deriving Generic
