feat(exam-correct): return user lookup result even for failure

This commit is contained in:
Gregor Kleen 2020-02-07 14:49:14 +01:00
parent 0d4dcf8658
commit 8e41820c9d
3 changed files with 36 additions and 23 deletions

View File

@ -1186,7 +1186,7 @@ MenuTutorialEdit: Tutorium editieren
MenuTutorialComm: Mitteilung an Teilnehmer MenuTutorialComm: Mitteilung an Teilnehmer
MenuExamList: Prüfungen MenuExamList: Prüfungen
MenuExamNew: Neue Prüfung anlegen MenuExamNew: Neue Prüfung anlegen
MenuExamEdit: Bearbeiten MenuExamEdit: Prüfung bearbeiten
MenuExamUsers: Teilnehmer MenuExamUsers: Teilnehmer
MenuExamGrades: Prüfungsleistungen MenuExamGrades: Prüfungsleistungen
MenuExamAddMembers: Prüfungsteilnehmer hinzufügen MenuExamAddMembers: Prüfungsteilnehmer hinzufügen
@ -1402,7 +1402,6 @@ ExamCorrectHeading examname@Text: Prüfungsergebnisse für #{examname} eintragen
ExamCorrectHeadDate: Zeit ExamCorrectHeadDate: Zeit
ExamCorrectHeadParticipant: Teilnehmer ExamCorrectHeadParticipant: Teilnehmer
ExamCorrectHeadParticipantTooltip:
ExamCorrectHeadPart exampartnum@ExamPartNumber: #{exampartnum} ExamCorrectHeadPart exampartnum@ExamPartNumber: #{exampartnum}
ExamCorrectHeadPartName exampartname@ExamPartName: #{exampartname} ExamCorrectHeadPartName exampartname@ExamPartName: #{exampartname}
ExamCorrectHeadStatus: Status ExamCorrectHeadStatus: Status
@ -1411,6 +1410,8 @@ ExamCorrectButtonSend: Senden
ExamCorrectErrorMultipleMatchingParticipants: Dem Identifikator konnten mehrere Prüfungsteilnehmer zugeordnet werden. ExamCorrectErrorMultipleMatchingParticipants: Dem Identifikator konnten mehrere Prüfungsteilnehmer zugeordnet werden.
ExamCorrectErrorNoMatchingParticipants: Dem Identifikator konnte kein Prüfungsteilnehmer zugeordnet werden. ExamCorrectErrorNoMatchingParticipants: Dem Identifikator konnte kein Prüfungsteilnehmer zugeordnet werden.
ExamCorrectErrorPartResultOutOfBounds examPartNumber@ExamPartNumber: Prüfungsergebnis für Teil #{examPartNumber} ist nicht größer Null.
ExamCorrectErrorPartResultOutOfBoundsMax examPartNumber@ExamPartNumber maxPoints@Points: Prüfungsergebnis für Teil #{examPartNumber} liegt nicht zwischen 0 und #{maxPoints}.
SubmissionUserInvitationAccepted shn@SheetName: Sie wurden als Mitabgebende(r) für eine Abgabe zu #{shn} eingetragen SubmissionUserInvitationAccepted shn@SheetName: Sie wurden als Mitabgebende(r) für eine Abgabe zu #{shn} eingetragen
SubmissionUserInvitationDeclined shn@SheetName: Sie haben die Einladung, Mitabgebende(r) für #{shn} zu werden, abgelehnt SubmissionUserInvitationDeclined shn@SheetName: Sie haben die Einladung, Mitabgebende(r) für #{shn} zu werden, abgelehnt

View File

@ -1185,7 +1185,7 @@ MenuTutorialEdit: Edit tutorial
MenuTutorialComm: Send course message MenuTutorialComm: Send course message
MenuExamList: Exams MenuExamList: Exams
MenuExamNew: Create new exam MenuExamNew: Create new exam
MenuExamEdit: Edit MenuExamEdit: Edit exam
MenuExamUsers: Participants MenuExamUsers: Participants
MenuExamGrades: Exam results MenuExamGrades: Exam results
MenuExamAddMembers: Add exam participants MenuExamAddMembers: Add exam participants
@ -1408,6 +1408,8 @@ ExamCorrectButtonSend: Submit
ExamCorrectErrorMultipleMatchingParticipants: This identifier matches on multiple exam participants. ExamCorrectErrorMultipleMatchingParticipants: This identifier matches on multiple exam participants.
ExamCorrectErrorNoMatchingParticipants: This identifier does not match on any exam participant. ExamCorrectErrorNoMatchingParticipants: This identifier does not match on any exam participant.
ExamCorrectErrorPartResultOutOfBounds examPartNumber: Exam part result for #{examPartNumber} ist not greater zero.
ExamCorrectErrorPartResultOutOfBoundsMax examPartNumber maxPoints: Exam part result for #{examPartNumber} is not between 0 and #{maxPoints}.
SubmissionUserInvitationAccepted shn: You now participate in a submission for #{shn} SubmissionUserInvitationAccepted shn: You now participate in a submission for #{shn}
SubmissionUserInvitationDeclined shn: You have declined the invitation to participate in a submission for #{shn} SubmissionUserInvitationDeclined shn: You have declined the invitation to participate in a submission for #{shn}
@ -1629,6 +1631,7 @@ ExamFormCorrection: Correction
ExamFormParts: Exam parts ExamFormParts: Exam parts
ExamCorrectors: Correctors ExamCorrectors: Correctors
ExamCorrectorsTip: Correctors configured here may, after the start of the exam and until "Results visible from", enter exam part results for all exam parts and participants.
ExamCorrectorAlreadyAdded: A corrector with this email address already exists ExamCorrectorAlreadyAdded: A corrector with this email address already exists
ExamParts: Exam parts/questions ExamParts: Exam parts/questions

View File

@ -38,7 +38,8 @@ data CorrectInterfaceResponse
, ciraMessage :: Text , ciraMessage :: Text
} }
| CorrectInterfaceResponseFailure | CorrectInterfaceResponseFailure
{ cirfMessage :: Text { cirfUser :: Maybe CorrectInterfaceUser
, cirfMessage :: Text
} }
| CorrectInterfaceResponseNoOp | CorrectInterfaceResponseNoOp
{ cirnUsers :: Set CorrectInterfaceUser { cirnUsers :: Set CorrectInterfaceUser
@ -103,11 +104,11 @@ postECorrectR tid ssh csh examn = do
CorrectInterfaceRequest{..} <- requireCheckJsonBody CorrectInterfaceRequest{..} <- requireCheckJsonBody
response <- runDB $ do response <- exceptT return return . hoist runDB $ do
Entity eId Exam{..} <- fetchExam tid ssh csh examn Entity eId Exam{..} <- lift $ fetchExam tid ssh csh examn
euid <- traverse decrypt ciqUser euid <- traverse decrypt ciqUser
participantMatches <- E.select . E.from $ \(examRegistration `E.InnerJoin` user) -> do participantMatches <- lift . E.select . E.from $ \(examRegistration `E.InnerJoin` user) -> do
E.on $ examRegistration E.^. ExamRegistrationUser E.==. user E.^. UserId E.on $ examRegistration E.^. ExamRegistrationUser E.==. user E.^. UserId
E.where_ $ examRegistration E.^. ExamRegistrationExam E.==. E.val eId E.where_ $ examRegistration E.^. ExamRegistrationExam E.==. E.val eId
@ -150,10 +151,10 @@ postECorrectR tid ssh csh examn = do
now <- liftIO getCurrentTime now <- liftIO getCurrentTime
newExamPartResults <- if newExamPartResults <- if
| Just results <- ciqResults -> iforM (toNullable results) $ \partNumber mPartResult -> do | Just results <- ciqResults -> iforM (toNullable results) $ \partNumber mPartResult -> do
(Entity examPartId ExamPart{..}) <- getBy404 $ UniqueExamPartNumber eId partNumber (Entity examPartId ExamPart{..}) <- lift . getBy404 $ UniqueExamPartNumber eId partNumber
mOldResult <- getBy $ UniqueExamPartResult examPartId uid mOldResult <- lift . getBy $ UniqueExamPartResult examPartId uid
if if
| Just (Entity oldId _) <- mOldResult, is _Nothing mPartResult -> do | Just (Entity oldId _) <- mOldResult, is _Nothing mPartResult -> lift $ do
delete oldId delete oldId
audit $ TransactionExamPartResultDeleted examPartId uid audit $ TransactionExamPartResultDeleted examPartId uid
return Nothing return Nothing
@ -162,29 +163,36 @@ postECorrectR tid ssh csh examn = do
mNew = ExamAttended <$> mPartResult mNew = ExamAttended <$> mPartResult
resultVal = _entityVal . _examPartResultResult resultVal = _entityVal . _examPartResultResult
in if in if
| mOld /= mNew -> let | mOld /= mNew -> do
-- cut off part results that exceed the maximum number of points for this exam part for now let
-- TODO answer with new failure response type instead partResultAcceptable = 0 <= partResult
partResult' = if && maybe True (partResult <=) examPartMaxPoints
| Just maxPts <- examPartMaxPoints, maxPts < partResult -> maxPts guardMExceptT partResultAcceptable $
| otherwise -> partResult let
in do msg | Just maxPoints <- examPartMaxPoints
newExamPartResult <- upsert ExamPartResult = MsgExamCorrectErrorPartResultOutOfBoundsMax partNumber maxPoints
| otherwise
= MsgExamCorrectErrorPartResultOutOfBounds partNumber
in CorrectInterfaceResponseFailure
<$> (Just <$> userToResponse match)
<*> (getMessageRender <*> pure msg)
newExamPartResult <- lift $ upsert ExamPartResult
{ examPartResultExamPart = examPartId { examPartResultExamPart = examPartId
, examPartResultUser = uid , examPartResultUser = uid
, examPartResultResult = ExamAttended partResult' , examPartResultResult = ExamAttended partResult
, examPartResultLastChanged = now , examPartResultLastChanged = now
} }
[ ExamPartResultResult =. ExamAttended partResult' [ ExamPartResultResult =. ExamAttended partResult
, ExamPartResultLastChanged =. now , ExamPartResultLastChanged =. now
] ]
audit $ TransactionExamPartResultEdit examPartId uid lift . audit $ TransactionExamPartResultEdit examPartId uid
return $ newExamPartResult ^? resultVal return $ newExamPartResult ^? resultVal
| otherwise -> return $ mOldResult ^? _Just . resultVal | otherwise -> return $ mOldResult ^? _Just . resultVal
| otherwise -> return Nothing | otherwise -> return Nothing
| otherwise -> return mempty | otherwise -> return mempty
newExamResult <- do newExamResult <- lift $ do
mOldResult <- getBy $ UniqueExamResult eId uid mOldResult <- getBy $ UniqueExamResult eId uid
if if
| Just (Entity oldId _) <- mOldResult, is _Nothing ciqGrade -> do | Just (Entity oldId _) <- mOldResult, is _Nothing ciqGrade -> do
@ -222,7 +230,8 @@ postECorrectR tid ssh csh examn = do
-- on match with no exam participant, answer with 400 -- on match with no exam participant, answer with 400
| [] <- participantMatches -> return CorrectInterfaceResponseFailure | [] <- participantMatches -> return CorrectInterfaceResponseFailure
{ cirfMessage = mr MsgExamCorrectErrorNoMatchingParticipants { cirfUser = Nothing
, cirfMessage = mr MsgExamCorrectErrorNoMatchingParticipants
} }
-- on match with multiple exam participants, answer with 400 and a set of all matches -- on match with multiple exam participants, answer with 400 and a set of all matches