feat(course): associate qualifications with courses

This commit is contained in:
Steffen Jost 2023-03-06 17:27:57 +00:00
parent a9cccef1a5
commit ffaaf9c86d
3 changed files with 52 additions and 26 deletions

View File

@ -90,3 +90,10 @@ CourseUserExamOfficeOptOut
school SchoolId school SchoolId
UniqueCourseUserExamOfficeOptOut course user school UniqueCourseUserExamOfficeOptOut course user school
deriving Generic deriving Generic
CourseQualification
course CourseId
qualification QualificationId
sortOrder Int default=0
UniqueCourseQualification course qualification
deriving Generic

View File

@ -2,6 +2,8 @@
-- --
-- SPDX-License-Identifier: AGPL-3.0-or-later -- SPDX-License-Identifier: AGPL-3.0-or-later
{-# LANGUAGE TypeApplications #-}
module Handler.Tutorial.Users module Handler.Tutorial.Users
( getTUsersR, postTUsersR ( getTUsersR, postTUsersR
) where ) where
@ -20,7 +22,8 @@ import qualified Data.Map as Map
-- import qualified Data.Time.Zones as TZ -- import qualified Data.Time.Zones as TZ
import qualified Database.Esqueleto.Legacy as E import Database.Esqueleto.Experimental ((:&)(..))
import qualified Database.Esqueleto.Experimental as E -- needs TypeApplications Lang-Pragma
import Handler.Course.Users import Handler.Course.Users
@ -54,8 +57,17 @@ getTUsersR = postTUsersR
postTUsersR tid ssh csh tutn = do postTUsersR tid ssh csh tutn = do
showSex <- getShowSex showSex <- getShowSex
(Entity tutid Tutorial{..}, (participantRes, participantTable)) <- runDB $ do (Entity tutid Tutorial{..}, (participantRes, participantTable)) <- runDB $ do
cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh
tut@(Entity tutid _) <- fetchTutorial tid ssh csh tutn tut@(Entity tutid _) <- fetchTutorial tid ssh csh tutn
qualifications <- selectList [QualificationSchool ==. ssh] [Asc QualificationShorthand] -- qualifications <- selectList [QualificationSchool ==. ssh] [Asc QualificationShorthand]
qualifications <- E.select $ do
(qual :& courseQual) <-
E.from $ E.table @Qualification
`E.innerJoin` E.table @CourseQualification
`E.on` (\(qual :& courseQual) -> qual E.^. QualificationId E.==. courseQual E.^. CourseQualificationQualification)
E.where_ $ courseQual E.^. CourseQualificationCourse E.==. E.val cid
E.orderBy [E.asc $ courseQual E.^. CourseQualificationSortOrder]
pure qual
now <- liftIO getCurrentTime now <- liftIO getCurrentTime
let minDur :: Maybe Int = minimumMaybe $ catMaybes (view _qualificationValidDuration <$> qualifications) -- no instance Ord CalendarDiffDays let minDur :: Maybe Int = minimumMaybe $ catMaybes (view _qualificationValidDuration <$> qualifications) -- no instance Ord CalendarDiffDays
dayExpiry = flip addGregorianDurationClip (utctDay now) . fromMonths <$> minDur dayExpiry = flip addGregorianDurationClip (utctDay now) . fromMonths <$> minDur
@ -71,12 +83,12 @@ postTUsersR tid ssh csh tutn = do
& defaultSortingByName & defaultSortingByName
& restrictSorting (\name _ -> none (== name) ["note", "registration", "tutorials", "exams", "submission-group", "state"]) -- We need to be careful to restrict allowed sorting/filter to not expose sensitive information & restrictSorting (\name _ -> none (== name) ["note", "registration", "tutorials", "exams", "submission-group", "state"]) -- We need to be careful to restrict allowed sorting/filter to not expose sensitive information
& restrictFilter (\name _ -> none (== name) ["tutorial", "exam", "submission-group", "active", "has-personalised-sheet-files"]) & restrictFilter (\name _ -> none (== name) ["tutorial", "exam", "submission-group", "active", "has-personalised-sheet-files"])
isInTut q = E.exists . E.from $ \tutorialParticipant -> isInTut q = E.exists $ do
tutorialParticipant <- E.from $ E.table @TutorialParticipant
E.where_ $ tutorialParticipant E.^. TutorialParticipantUser E.==. queryUser q E.^. UserId E.where_ $ tutorialParticipant E.^. TutorialParticipantUser E.==. queryUser q E.^. UserId
E.&&. tutorialParticipant E.^. TutorialParticipantTutorial E.==. E.val tutid E.&&. tutorialParticipant E.^. TutorialParticipantTutorial E.==. E.val tutid
csvColChoices = flip elem ["name", "matriculation", "email", "qualifications"] csvColChoices = flip elem ["name", "matriculation", "email", "qualifications"]
cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh
let let
qualOpt :: Entity Qualification -> Handler (Option QualificationId) qualOpt :: Entity Qualification -> Handler (Option QualificationId)
qualOpt (Entity qualId qual) = do qualOpt (Entity qualId qual) = do
@ -87,17 +99,20 @@ postTUsersR tid ssh csh tutn = do
, optionExternalValue = tshow cQualId , optionExternalValue = tshow cQualId
} }
acts :: Map TutorialUserAction (AForm Handler TutorialUserActionData) acts :: Map TutorialUserAction (AForm Handler TutorialUserActionData)
acts = Map.fromList acts = Map.fromList $
[ ( TutorialUserRenewQualification (if null qualifications then mempty else
, TutorialUserRenewQualificationData [ ( TutorialUserRenewQualification
<$> apopt (selectField . fmap mkOptionList $ mapM qualOpt qualifications) (fslI MsgQualificationName) Nothing , TutorialUserRenewQualificationData
) <$> apopt (selectField . fmap mkOptionList $ mapM qualOpt qualifications) (fslI MsgQualificationName) Nothing
, ( TutorialUserGrantQualification )
, TutorialUserGrantQualificationData , ( TutorialUserGrantQualification
<$> apopt (selectField . fmap mkOptionList $ mapM qualOpt qualifications) (fslI MsgQualificationName) Nothing , TutorialUserGrantQualificationData
<*> apopt dayField (fslI MsgLmsQualificationValidUntil) dayExpiry <$> apopt (selectField . fmap mkOptionList $ mapM qualOpt qualifications) (fslI MsgQualificationName) Nothing
) <*> apopt dayField (fslI MsgLmsQualificationValidUntil) dayExpiry
, ( TutorialUserSendMail, pure TutorialUserSendMailData ) )
]
) ++
[ ( TutorialUserSendMail, pure TutorialUserSendMailData )
, ( TutorialUserDeregister, pure TutorialUserDeregisterData ) , ( TutorialUserDeregister, pure TutorialUserDeregisterData )
] ]
table <- makeCourseUserTable cid acts isInTut colChoices psValidator (Just csvColChoices) table <- makeCourseUserTable cid acts isInTut colChoices psValidator (Just csvColChoices)
@ -125,11 +140,11 @@ postTUsersR tid ssh csh tutn = do
addMessageI Success $ MsgTutorialUsersDeregistered nrDel addMessageI Success $ MsgTutorialUsersDeregistered nrDel
redirect $ CTutorialR tid ssh csh tutn TUsersR redirect $ CTutorialR tid ssh csh tutn TUsersR
tutors <- runDB $ tutors <- runDB $ E.select $ do
E.select $ E.from $ \(tutor `E.InnerJoin` user) -> do (tutor :& user) <- E.from $ E.table @Tutor `E.innerJoin` E.table @User
E.on $ tutor E.^. TutorUser E.==. user E.^. UserId `E.on` (\(tutor :& user) -> tutor E.^. TutorUser E.==. user E.^. UserId)
E.where_ $ tutor E.^. TutorTutorial E.==. E.val tutid E.where_ $ tutor E.^. TutorTutorial E.==. E.val tutid
return user return user
let heading = prependCourseTitle tid ssh csh $ CI.original tutorialName let heading = prependCourseTitle tid ssh csh $ CI.original tutorialName
siteLayoutMsg heading $ do siteLayoutMsg heading $ do

View File

@ -57,8 +57,8 @@ fillDb = do
addBDays = addBusinessDays Fraport -- holiday area to use addBDays = addBusinessDays Fraport -- holiday area to use
n_day n = addBDays n $ utctDay now n_day n = addBDays n $ utctDay now
n_day' n = now { utctDay = n_day n } n_day' n = now { utctDay = n_day n }
currentTerm = TermIdentifier . fst3 . toGregorian $ utctDay now (currentYear, _currentMonth, _currentDay) = toGregorian $ utctDay now
-- (currentYear, currentMonth, currentDay) = toGregorian $ getTermDay currentTerm currentTerm = TermIdentifier currentYear
nextTerm n = toEnum . (+n) $ fromEnum currentTerm nextTerm n = toEnum . (+n) $ fromEnum currentTerm
termTime :: TermIdentifier -- ^ Term termTime :: TermIdentifier -- ^ Term
@ -172,7 +172,7 @@ fillDb = do
, userTitle = Just "Dr." , userTitle = Just "Dr."
, userMaxFavourites = 14 , userMaxFavourites = 14
, userMaxFavouriteTerms = 4 , userMaxFavouriteTerms = 4
, userTheme = userDefaultTheme , userTheme = ThemeSkyLove
, userDateTimeFormat = userDefaultDateTimeFormat , userDateTimeFormat = userDefaultDateTimeFormat
, userDateFormat = userDefaultDateFormat , userDateFormat = userDefaultDateFormat
, userTimeFormat = userDefaultTimeFormat , userTimeFormat = userDefaultTimeFormat
@ -402,7 +402,7 @@ fillDb = do
, userTitle = Nothing , userTitle = Nothing
, userMaxFavourites = userDefaultMaxFavourites , userMaxFavourites = userDefaultMaxFavourites
, userMaxFavouriteTerms = userDefaultMaxFavourites , userMaxFavouriteTerms = userDefaultMaxFavourites
, userTheme = userDefaultTheme , userTheme = ThemeAberdeenReds
, userDateTimeFormat = userDefaultDateTimeFormat , userDateTimeFormat = userDefaultDateTimeFormat
, userDateFormat = userDefaultDateFormat , userDateFormat = userDefaultDateFormat
, userTimeFormat = userDefaultTimeFormat , userTimeFormat = userDefaultTimeFormat
@ -786,6 +786,7 @@ fillDb = do
jtt = (((Just .) .) .) . termTime tid jtt = (((Just .) .) .) . termTime tid
firstDay = utctDay $ termTime tid TermDayLectureStart 0 Nothing toMidnight firstDay = utctDay $ termTime tid TermDayLectureStart 0 Nothing toMidnight
secondDay = utctDay $ termTime tid TermDayLectureStart 1 Nothing toMidnight secondDay = utctDay $ termTime tid TermDayLectureStart 1 Nothing toMidnight
tyear = year tid
weekDay = dayOfWeek firstDay weekDay = dayOfWeek firstDay
-- thirdDay = utctDay $ termTime tid TermDayLectureStart 2 Nothing toMidnight -- thirdDay = utctDay $ termTime tid TermDayLectureStart 2 Nothing toMidnight
capacity = Just 8 capacity = Just 8
@ -818,6 +819,9 @@ fillDb = do
, courseMaterialFree = True , courseMaterialFree = True
} }
insert_ $ CourseEdit jost now c insert_ $ CourseEdit jost now c
when (tyear >= currentYear) $ insert_ $ CourseQualification c qid_f 2
when (tyear >= succ currentYear) $ insert_ $ CourseQualification c qid_r 3
when (tyear >= succ (succ currentYear)) $ insert_ $ CourseQualification c qid_l 1
insert_ Sheet insert_ Sheet
{ sheetCourse = c { sheetCourse = c
, sheetName = mkName "Sehtest" , sheetName = mkName "Sehtest"