-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

-- The files in /models determine t he database scheme.
-- The organisational split into several files has no operational effects.
-- White-space and case matters: Each SQL table is named in 1st column of this file
-- Indendent lower-case lines describe the SQL-columns of the table with name, type and options
-- Nullable columns have "Maybe" written after their type
-- Option "default=xyz" is only used for database migrations due to changes in the SQL-schema, also see Model.Migration
-- Indendent upper-case lines usually impose Uniqueness constraints for rows by some columns.
-- Each table will also have an column storing a unique numeric row key, unless there is a row Primary columnname
--
User json    -- Each Uni2work user has a corresponding row in this table; created upon first login.
    surname        UserSurname              -- Display user names always through 'nameWidget displayName surname'
    displayName    UserDisplayName
    displayEmail   UserEmail
    email          UserEmail                -- Case-insensitive eMail address, used for sending  TODO: make this nullable
    ident          UserIdent                -- Case-insensitive user-identifier
    authentication AuthenticationMode       -- 'AuthLDAP' or ('AuthPWHash'+password-hash)
    lastAuthentication UTCTime Maybe        -- last login date
    created        UTCTime default=now()
    lastLdapSynchronisation UTCTime Maybe
    lastAzureSynchronisation UTCTime Maybe
    ldapPrimaryKey UserEduPersonPrincipalName Maybe
    azurePrimaryKey UUID Maybe
    tokensIssuedAfter  UTCTime Maybe        -- do not accept bearer tokens issued before this time (accept all tokens if null)
    matrikelnummer UserMatriculation Maybe  -- usually a number; AVS Personalnummer; nicht Fraport Personalnummer!
    firstName      Text                     -- For export in tables, pre-split firstName from displayName
    title          Text Maybe               -- For upcoming name customisation
    maxFavourites  Int default=12           -- max number of non-manual entries in favourites bar (pruned only if below a set importance threshold)
    maxFavouriteTerms Int default=2         -- max number of term-sections in favourites bar
    theme          Theme default='ThemeDefault'  -- Color-theme of the frontend; user-defined
    dateTimeFormat DateTimeFormat "default='%d %b %y %R'" -- preferred Date+Time display format for user; user-defined
    dateFormat     DateTimeFormat "default='%d %b %Y'"       -- preferred Date-only display format for user; user-defined
    timeFormat     DateTimeFormat "default='%R'"             -- preferred Time-only display format for user; user-defined
    downloadFiles  Bool default=false           -- Should files be opened in browser or downloaded? (users often oblivious that their browser has a setting for this)
    languages      Languages Maybe          -- Preferred language; user-defined
    notificationSettings NotificationSettings  "default='{}'::jsonb"   -- Bit-array for which events email notifications are requested by user; user-defined; missing fields in json object will be parsed to default trigger
    warningDays    NominalDiffTime default=1209600 -- timedistance to pending deadlines for homepage infos
    csvOptions     CsvOptions "default='{}'::jsonb"
    sex            Sex Maybe  -- currently ignored
    birthday       Day Maybe  -- for better identification
    showSex        Bool default=false
    telephone      Text Maybe            
    mobile         Text Maybe
    companyPersonalNumber Text Maybe -- Company will become a new table, but if company=fraport, some information is received via LDAP 
    companyDepartment     Text Maybe -- thus we store such information for ease of reference directly, if available 
    pinPassword           Text Maybe -- used to encrypt pins within emails
    postAddress           StoredMarkup Maybe 
    postLastUpdate        UTCTime Maybe -- record postal address updates
    prefersPostal         Bool default=false    -- user prefers letters by post instead of email
    examOfficeGetSynced   Bool default=true     -- whether synced status should be displayed for exam results by default
    examOfficeGetLabels   Bool default=true     -- whether labels should be displayed for exam results by default
    UniqueAuthentication ident                  -- Column 'ident' can be used as a row-key in this table
    UniqueEmail email                           -- Column 'email' can be used as a row-key in this table
    UniqueLdapPrimaryKey ldapPrimaryKey !force  -- Column 'ldapPrimaryKey' is either empty or contains a unique value
    UniqueAzurePrimaryKey azurePrimaryKey !force  -- Column 'azurePrimaryKey' is either empty or contains a unique value
    deriving Show Eq Ord Generic                -- Haskell-specific settings for runtime-value representing a row in memory

UserFunction -- Administratively assigned functions (lecturer, admin, evaluation, ...)
    user     UserId
    school   SchoolId
    function SchoolFunction
    UniqueUserFunction user school function
    deriving Generic
UserSystemFunction
    user     UserId
    function SystemFunction   -- Defined in Model.Types.User
    manual   Bool             -- Inserted manually by Admin or automatic from LDAP
    isOptOut Bool             -- User has currently deactivate the role for themselves
    UniqueUserSystemFunction user function
    deriving Generic
UserExamOffice
    user      UserId
    field     StudyTermsId
    UniqueUserExamOffice user field
    deriving Generic
UserSchool -- Managed by users themselves, encodes "schools of interest"
    user     UserId
    school   SchoolId
    isOptOut Bool     -- true if this a marker, that the user manually deleted this entry; it should not be recreated automatically 
    UniqueUserSchool user school
    deriving Generic
UserGroupMember
    group         UserGroupName
    user          UserId
    primary       Checkmark nullable
    UniquePrimaryUserGroupMember group primary !force
    UniqueUserGroupMember group user
    deriving Generic
UserCompany 
    user                  UserId  
    company               CompanyId  OnDeleteCascade OnUpdateCascade
    supervisor            Bool       default=false -- should this user be made supervisor for all _new_ users associated with this company?        
    supervisorReroute     Bool       default=false -- if supervisor is true, should this supervisor receive email for _new_ company users?
    UniqueUserCompany user company   -- a user may belong to multiple companies, but to each one only once
    deriving Generic
UserSupervisor
    supervisor            UserId -- multiple supervisor per trainee possible
    user                  UserId
    rerouteNotifications  Bool   -- User can be his own supervisor to receive notifications as well
    UniqueUserSupervisor supervisor user -- each supervisor/user combination is unique (same supervisor can superviser the same user only once)
    deriving Generic
    
