fix(cron): work around extraneous sheet notifications
This commit is contained in:
parent
9a35c8542c
commit
cbe211bf23
@ -162,54 +162,57 @@ determineCrontab = execWriterT $ do
|
|||||||
|
|
||||||
let
|
let
|
||||||
sheetJobs (Entity nSheet Sheet{..}) = do
|
sheetJobs (Entity nSheet Sheet{..}) = do
|
||||||
for_ sheetActiveFrom $ \aFrom ->
|
for_ (max <$> sheetVisibleFrom <*> sheetActiveFrom) $ \aFrom ->
|
||||||
tell $ HashMap.singleton
|
tell $ HashMap.singleton
|
||||||
(JobCtlQueue $ JobQueueNotification NotificationSheetActive{..})
|
(JobCtlQueue $ JobQueueNotification NotificationSheetActive{..})
|
||||||
Cron
|
Cron
|
||||||
{ cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom aFrom
|
{ cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ aFrom
|
||||||
, cronRepeat = CronRepeatOnChange
|
, cronRepeat = CronRepeatNever
|
||||||
, cronRateLimit = appNotificationRateLimit
|
, cronRateLimit = appNotificationRateLimit
|
||||||
, cronNotAfter = maybe (Left appNotificationExpiration) (Right . CronTimestamp . utcToLocalTimeTZ appTZ) sheetActiveTo
|
, cronNotAfter = maybe (Left appNotificationExpiration) (Right . CronTimestamp . utcToLocalTimeTZ appTZ) sheetActiveTo
|
||||||
}
|
}
|
||||||
for_ sheetHintFrom $ \hFrom -> maybeT (return ()) $ do
|
for_ (max <$> sheetVisibleFrom <*> sheetHintFrom) $ \hFrom -> maybeT (return ()) $ do
|
||||||
guard $ maybe True (\aFrom -> abs (diffUTCTime aFrom hFrom) > 300) sheetActiveFrom
|
guard $ maybe True (\aFrom -> abs (diffUTCTime aFrom hFrom) > 300) sheetActiveFrom
|
||||||
|
guardM $ or2M (return $ maybe True (\sFrom -> abs (diffUTCTime sFrom hFrom) > 300) sheetSolutionFrom)
|
||||||
|
(fmap not . lift . lift $ exists [SheetFileType ==. SheetSolution, SheetFileSheet ==. nSheet])
|
||||||
guardM . lift . lift $ exists [SheetFileType ==. SheetHint, SheetFileSheet ==. nSheet]
|
guardM . lift . lift $ exists [SheetFileType ==. SheetHint, SheetFileSheet ==. nSheet]
|
||||||
tell $ HashMap.singleton
|
tell $ HashMap.singleton
|
||||||
(JobCtlQueue $ JobQueueNotification NotificationSheetHint{..})
|
(JobCtlQueue $ JobQueueNotification NotificationSheetHint{..})
|
||||||
Cron
|
Cron
|
||||||
{ cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom hFrom
|
{ cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ hFrom
|
||||||
, cronRepeat = CronRepeatOnChange
|
, cronRepeat = CronRepeatNever
|
||||||
, cronRateLimit = appNotificationRateLimit
|
, cronRateLimit = appNotificationRateLimit
|
||||||
, cronNotAfter = Left appNotificationExpiration
|
, cronNotAfter = maybe (Left appNotificationExpiration) (Right . CronTimestamp . utcToLocalTimeTZ appTZ) sheetActiveTo
|
||||||
}
|
}
|
||||||
for_ sheetSolutionFrom $ \hFrom -> maybeT (return ()) $ do
|
for_ (max <$> sheetVisibleFrom <*> sheetSolutionFrom) $ \sFrom -> maybeT (return ()) $ do
|
||||||
guard $ maybe True (\aFrom -> abs (diffUTCTime aFrom hFrom) > 300) sheetActiveFrom
|
guard $ maybe True (\aFrom -> abs (diffUTCTime aFrom sFrom) > 300) sheetActiveFrom
|
||||||
guardM . lift . lift $ exists [SheetFileType ==. SheetSolution, SheetFileSheet ==. nSheet]
|
guardM . lift . lift $ exists [SheetFileType ==. SheetSolution, SheetFileSheet ==. nSheet]
|
||||||
tell $ HashMap.singleton
|
tell $ HashMap.singleton
|
||||||
(JobCtlQueue $ JobQueueNotification NotificationSheetSolution{..})
|
(JobCtlQueue $ JobQueueNotification NotificationSheetSolution{..})
|
||||||
Cron
|
Cron
|
||||||
{ cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom hFrom
|
{ cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ sFrom
|
||||||
, cronRepeat = CronRepeatOnChange
|
, cronRepeat = CronRepeatNever
|
||||||
, cronRateLimit = appNotificationRateLimit
|
, cronRateLimit = appNotificationRateLimit
|
||||||
, cronNotAfter = Left appNotificationExpiration
|
, cronNotAfter = Left nominalDay
|
||||||
}
|
}
|
||||||
for_ sheetActiveTo $ \aTo -> do
|
for_ sheetActiveTo $ \aTo -> do
|
||||||
tell $ HashMap.singleton
|
whenIsJust (max aTo <$> sheetVisibleFrom) $ \aTo' -> do
|
||||||
(JobCtlQueue $ JobQueueNotification NotificationSheetSoonInactive{..})
|
tell $ HashMap.singleton
|
||||||
Cron
|
(JobCtlQueue $ JobQueueNotification NotificationSheetSoonInactive{..})
|
||||||
{ cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ . maybe id max sheetActiveFrom . maybe id max sheetVisibleFrom $ addUTCTime (-nominalDay) aTo
|
Cron
|
||||||
, cronRepeat = CronRepeatOnChange -- Allow repetition of the notification (if something changes), but wait at least an hour
|
{ cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ . maybe id max sheetActiveFrom $ addUTCTime (-nominalDay) aTo'
|
||||||
, cronRateLimit = appNotificationRateLimit
|
, cronRepeat = CronRepeatOnChange -- Allow repetition of the notification (if something changes), but wait at least an hour
|
||||||
, cronNotAfter = Right . CronTimestamp $ utcToLocalTimeTZ appTZ aTo
|
, cronRateLimit = appNotificationRateLimit
|
||||||
}
|
, cronNotAfter = Right . CronTimestamp $ utcToLocalTimeTZ appTZ aTo
|
||||||
tell $ HashMap.singleton
|
}
|
||||||
(JobCtlQueue $ JobQueueNotification NotificationSheetInactive{..})
|
tell $ HashMap.singleton
|
||||||
Cron
|
(JobCtlQueue $ JobQueueNotification NotificationSheetInactive{..})
|
||||||
{ cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom aTo
|
Cron
|
||||||
, cronRepeat = CronRepeatOnChange
|
{ cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ aTo
|
||||||
, cronRateLimit = appNotificationRateLimit
|
, cronRepeat = CronRepeatOnChange
|
||||||
, cronNotAfter = Left appNotificationExpiration
|
, cronRateLimit = appNotificationRateLimit
|
||||||
}
|
, cronNotAfter = Left appNotificationExpiration
|
||||||
|
}
|
||||||
when sheetAutoDistribute $
|
when sheetAutoDistribute $
|
||||||
tell $ HashMap.singleton
|
tell $ HashMap.singleton
|
||||||
(JobCtlQueue $ JobDistributeCorrections nSheet)
|
(JobCtlQueue $ JobDistributeCorrections nSheet)
|
||||||
|
|||||||
@ -15,82 +15,82 @@ import qualified Data.Set as Set
|
|||||||
import Handler.Utils.ExamOffice.Exam
|
import Handler.Utils.ExamOffice.Exam
|
||||||
import Handler.Utils.ExamOffice.ExternalExam
|
import Handler.Utils.ExamOffice.ExternalExam
|
||||||
|
|
||||||
|
import qualified Data.Conduit.Combinators as C
|
||||||
|
|
||||||
|
|
||||||
dispatchJobQueueNotification :: Notification -> JobHandler UniWorX
|
dispatchJobQueueNotification :: Notification -> JobHandler UniWorX
|
||||||
dispatchJobQueueNotification jNotification = JobHandlerAtomic $ do
|
dispatchJobQueueNotification jNotification = JobHandlerAtomic $ do
|
||||||
candidates <- hoist lift $ determineNotificationCandidates jNotification
|
|
||||||
nClass <- hoist lift $ classifyNotification jNotification
|
nClass <- hoist lift $ classifyNotification jNotification
|
||||||
mapM_ (queueDBJob . flip JobSendNotification jNotification) $ do
|
runConduit $ transPipe (hoist lift) (determineNotificationCandidates jNotification)
|
||||||
Entity uid User{userNotificationSettings} <- candidates
|
.| C.filter (\(Entity _ User{userNotificationSettings}) -> notificationAllowed userNotificationSettings nClass)
|
||||||
guard $ notificationAllowed userNotificationSettings nClass
|
.| C.map (flip JobSendNotification jNotification . entityKey) .| sinkDBJobs
|
||||||
return uid
|
|
||||||
|
|
||||||
|
|
||||||
determineNotificationCandidates :: Notification -> DB [Entity User]
|
determineNotificationCandidates :: Notification -> ConduitT () (Entity User) DB ()
|
||||||
determineNotificationCandidates NotificationSubmissionRated{..}
|
determineNotificationCandidates NotificationSubmissionRated{..}
|
||||||
= E.select . E.from $ \(user `E.InnerJoin` submissionUser) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
= E.selectSource . E.from $ \(user `E.InnerJoin` submissionUser) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ user E.^. UserId E.==. submissionUser E.^. SubmissionUserUser
|
E.on $ user E.^. UserId E.==. submissionUser E.^. SubmissionUserUser
|
||||||
E.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val nSubmission
|
E.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val nSubmission
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationSheetActive{..}
|
determineNotificationCandidates NotificationSheetActive{..}
|
||||||
= E.select . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
= E.selectSource . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
||||||
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
||||||
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
||||||
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationSheetHint{..}
|
determineNotificationCandidates NotificationSheetHint{..}
|
||||||
= E.select . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
= E.selectSource . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
||||||
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
||||||
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
||||||
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationSheetSolution{..}
|
determineNotificationCandidates NotificationSheetSolution{..}
|
||||||
= E.select . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
= E.selectSource . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
||||||
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
||||||
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
||||||
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationSheetSoonInactive{..}
|
determineNotificationCandidates NotificationSheetSoonInactive{..}
|
||||||
= E.select . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
= E.selectSource . E.from $ \(user `E.InnerJoin` courseParticipant `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
E.on $ sheet E.^. SheetCourse E.==. courseParticipant E.^. CourseParticipantCourse
|
||||||
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
E.on $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser
|
||||||
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
||||||
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationSheetInactive{..}
|
determineNotificationCandidates NotificationSheetInactive{..}
|
||||||
= E.select . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
= E.selectSource . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ lecturer E.^. LecturerCourse E.==. sheet E.^. SheetCourse
|
E.on $ lecturer E.^. LecturerCourse E.==. sheet E.^. SheetCourse
|
||||||
E.on $ lecturer E.^. LecturerUser E.==. user E.^. UserId
|
E.on $ lecturer E.^. LecturerUser E.==. user E.^. UserId
|
||||||
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationCorrectionsAssigned{..}
|
determineNotificationCandidates NotificationCorrectionsAssigned{..}
|
||||||
= selectList [UserId ==. nUser] []
|
= selectSource [UserId ==. nUser] []
|
||||||
determineNotificationCandidates NotificationCorrectionsNotDistributed{nSheet}
|
determineNotificationCandidates NotificationCorrectionsNotDistributed{nSheet}
|
||||||
= E.select . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
= E.selectSource . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` sheet) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ lecturer E.^. LecturerCourse E.==. sheet E.^. SheetCourse
|
E.on $ lecturer E.^. LecturerCourse E.==. sheet E.^. SheetCourse
|
||||||
E.on $ lecturer E.^. LecturerUser E.==. user E.^. UserId
|
E.on $ lecturer E.^. LecturerUser E.==. user E.^. UserId
|
||||||
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
E.where_ $ sheet E.^. SheetId E.==. E.val nSheet
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationUserRightsUpdate{..} = do
|
determineNotificationCandidates NotificationUserRightsUpdate{..} = do
|
||||||
-- always send to affected user
|
-- always send to affected user
|
||||||
affectedUser <- selectList [UserId ==. nUser] []
|
affectedUser <- lift $ selectList [UserId ==. nUser] []
|
||||||
-- send to same-school admins only if there was an update
|
-- send to same-school admins only if there was an update
|
||||||
currentAdminSchools <- setOf (folded . _entityVal . _userFunctionSchool) <$> selectList [UserFunctionUser ==. nUser, UserFunctionFunction ==. SchoolAdmin] []
|
currentAdminSchools <- lift $ setOf (folded . _entityVal . _userFunctionSchool) <$> selectList [UserFunctionUser ==. nUser, UserFunctionFunction ==. SchoolAdmin] []
|
||||||
let oldAdminSchools = setOf (folded . filtered ((== SchoolAdmin) . view _1) . _2 . from _SchoolId) nOriginalRights
|
let oldAdminSchools = setOf (folded . filtered ((== SchoolAdmin) . view _1) . _2 . from _SchoolId) nOriginalRights
|
||||||
newAdminSchools = currentAdminSchools `Set.difference` oldAdminSchools
|
newAdminSchools = currentAdminSchools `Set.difference` oldAdminSchools
|
||||||
affectedAdmins <- E.select . E.from $ \(user `E.InnerJoin` admin) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
affectedAdmins <- lift . E.select . E.from $ \(user `E.InnerJoin` admin) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ admin E.^. UserFunctionUser E.==. user E.^. UserId
|
E.on $ admin E.^. UserFunctionUser E.==. user E.^. UserId
|
||||||
E.where_ $ admin E.^. UserFunctionSchool `E.in_` E.valList (Set.toList newAdminSchools)
|
E.where_ $ admin E.^. UserFunctionSchool `E.in_` E.valList (Set.toList newAdminSchools)
|
||||||
E.&&. admin E.^. UserFunctionFunction E.==. E.val SchoolAdmin
|
E.&&. admin E.^. UserFunctionFunction E.==. E.val SchoolAdmin
|
||||||
return user
|
return user
|
||||||
return . nub $ affectedUser <> affectedAdmins
|
yieldMany . nub $ affectedUser <> affectedAdmins
|
||||||
determineNotificationCandidates NotificationUserAuthModeUpdate{..}
|
determineNotificationCandidates NotificationUserAuthModeUpdate{..}
|
||||||
= selectList [UserId ==. nUser] []
|
= selectSource [UserId ==. nUser] []
|
||||||
determineNotificationCandidates NotificationExamRegistrationActive{..} =
|
determineNotificationCandidates NotificationExamRegistrationActive{..} =
|
||||||
E.select . E.from $ \(exam `E.InnerJoin` courseParticipant `E.InnerJoin` user) -> do
|
E.selectSource . E.from $ \(exam `E.InnerJoin` courseParticipant `E.InnerJoin` user) -> do
|
||||||
E.on $ courseParticipant E.^. CourseParticipantUser E.==. user E.^. UserId
|
E.on $ courseParticipant E.^. CourseParticipantUser E.==. user E.^. UserId
|
||||||
E.on $ courseParticipant E.^. CourseParticipantCourse E.==. exam E.^. ExamCourse
|
E.on $ courseParticipant E.^. CourseParticipantCourse E.==. exam E.^. ExamCourse
|
||||||
E.where_ $ exam E.^. ExamId E.==. E.val nExam
|
E.where_ $ exam E.^. ExamId E.==. E.val nExam
|
||||||
@ -100,7 +100,7 @@ determineNotificationCandidates NotificationExamRegistrationActive{..} =
|
|||||||
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationExamRegistrationSoonInactive{..} =
|
determineNotificationCandidates NotificationExamRegistrationSoonInactive{..} =
|
||||||
E.select . E.from $ \(exam `E.InnerJoin` courseParticipant `E.InnerJoin` user) -> do
|
E.selectSource . E.from $ \(exam `E.InnerJoin` courseParticipant `E.InnerJoin` user) -> do
|
||||||
E.on $ courseParticipant E.^. CourseParticipantUser E.==. user E.^. UserId
|
E.on $ courseParticipant E.^. CourseParticipantUser E.==. user E.^. UserId
|
||||||
E.on $ courseParticipant E.^. CourseParticipantCourse E.==. exam E.^. ExamCourse
|
E.on $ courseParticipant E.^. CourseParticipantCourse E.==. exam E.^. ExamCourse
|
||||||
E.where_ $ exam E.^. ExamId E.==. E.val nExam
|
E.where_ $ exam E.^. ExamId E.==. E.val nExam
|
||||||
@ -110,21 +110,21 @@ determineNotificationCandidates NotificationExamRegistrationSoonInactive{..} =
|
|||||||
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationExamDeregistrationSoonInactive{..} =
|
determineNotificationCandidates NotificationExamDeregistrationSoonInactive{..} =
|
||||||
E.select . E.from $ \(examRegistration `E.InnerJoin` user) -> do
|
E.selectSource . 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 nExam
|
E.where_ $ examRegistration E.^. ExamRegistrationExam E.==. E.val nExam
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates notif@NotificationExamResult{..} = do
|
determineNotificationCandidates notif@NotificationExamResult{..} = do
|
||||||
lastExec <- fmap (fmap $ cronLastExecTime . entityVal) . getBy . UniqueCronLastExec . toJSON $ JobQueueNotification notif
|
lastExec <- lift . fmap (fmap $ cronLastExecTime . entityVal) . getBy . UniqueCronLastExec . toJSON $ JobQueueNotification notif
|
||||||
E.select . E.from $ \(examResult `E.InnerJoin` user) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
E.selectSource . E.from $ \(examResult `E.InnerJoin` user) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ examResult E.^. ExamResultUser E.==. user E.^. UserId
|
E.on $ examResult E.^. ExamResultUser E.==. user E.^. UserId
|
||||||
E.where_ $ examResult E.^. ExamResultExam E.==. E.val nExam
|
E.where_ $ examResult E.^. ExamResultExam E.==. E.val nExam
|
||||||
whenIsJust lastExec $ \lastExec' ->
|
whenIsJust lastExec $ \lastExec' ->
|
||||||
E.where_ $ examResult E.^. ExamResultLastChanged E.>. E.val lastExec'
|
E.where_ $ examResult E.^. ExamResultLastChanged E.>. E.val lastExec'
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationAllocationStaffRegister{..} = do
|
determineNotificationCandidates NotificationAllocationStaffRegister{..} = do
|
||||||
Allocation{..} <- getJust nAllocation
|
Allocation{..} <- lift $ getJust nAllocation
|
||||||
E.select . E.from $ \(user `E.InnerJoin` userFunction) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
E.selectSource . E.from $ \(user `E.InnerJoin` userFunction) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ user E.^. UserId E.==. userFunction E.^. UserFunctionUser
|
E.on $ user E.^. UserId E.==. userFunction E.^. UserFunctionUser
|
||||||
E.&&. userFunction E.^. UserFunctionSchool E.==. E.val allocationSchool
|
E.&&. userFunction E.^. UserFunctionSchool E.==. E.val allocationSchool
|
||||||
E.&&. userFunction E.^. UserFunctionFunction E.==. E.val SchoolLecturer
|
E.&&. userFunction E.^. UserFunctionFunction E.==. E.val SchoolLecturer
|
||||||
@ -143,7 +143,7 @@ determineNotificationCandidates NotificationAllocationStaffRegister{..} = do
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationAllocationAllocation{..} =
|
determineNotificationCandidates NotificationAllocationAllocation{..} =
|
||||||
E.select . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` course `E.InnerJoin` allocationCourse) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
E.selectSource . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` course `E.InnerJoin` allocationCourse) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ allocationCourse E.^. AllocationCourseCourse E.==. course E.^. CourseId
|
E.on $ allocationCourse E.^. AllocationCourseCourse E.==. course E.^. CourseId
|
||||||
E.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation
|
E.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation
|
||||||
E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse
|
E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse
|
||||||
@ -162,7 +162,7 @@ determineNotificationCandidates NotificationAllocationAllocation{..} =
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationAllocationUnratedApplications{..} =
|
determineNotificationCandidates NotificationAllocationUnratedApplications{..} =
|
||||||
E.select . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` course `E.InnerJoin` allocationCourse) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
E.selectSource . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` course `E.InnerJoin` allocationCourse) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ allocationCourse E.^. AllocationCourseCourse E.==. course E.^. CourseId
|
E.on $ allocationCourse E.^. AllocationCourseCourse E.==. course E.^. CourseId
|
||||||
E.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation
|
E.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation
|
||||||
E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse
|
E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse
|
||||||
@ -176,8 +176,8 @@ determineNotificationCandidates NotificationAllocationUnratedApplications{..} =
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationAllocationRegister{..} = do
|
determineNotificationCandidates NotificationAllocationRegister{..} = do
|
||||||
Allocation{..} <- getJust nAllocation
|
Allocation{..} <- lift $ getJust nAllocation
|
||||||
E.select . E.from $ \user -> do
|
E.selectSource . E.from $ \user -> do
|
||||||
E.where_ . E.exists . E.from $ \userSchool ->
|
E.where_ . E.exists . E.from $ \userSchool ->
|
||||||
E.where_ $ userSchool E.^. UserSchoolUser E.==. user E.^. UserId
|
E.where_ $ userSchool E.^. UserSchoolUser E.==. user E.^. UserId
|
||||||
E.&&. userSchool E.^. UserSchoolSchool E.==. E.val allocationSchool
|
E.&&. userSchool E.^. UserSchoolSchool E.==. E.val allocationSchool
|
||||||
@ -189,7 +189,7 @@ determineNotificationCandidates NotificationAllocationRegister{..} = do
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationAllocationOutdatedRatings{..} =
|
determineNotificationCandidates NotificationAllocationOutdatedRatings{..} =
|
||||||
E.select . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` course `E.InnerJoin` allocationCourse) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
E.selectSource . E.from $ \(user `E.InnerJoin` lecturer `E.InnerJoin` course `E.InnerJoin` allocationCourse) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do
|
||||||
E.on $ allocationCourse E.^. AllocationCourseCourse E.==. course E.^. CourseId
|
E.on $ allocationCourse E.^. AllocationCourseCourse E.==. course E.^. CourseId
|
||||||
E.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation
|
E.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation
|
||||||
E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse
|
E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse
|
||||||
@ -203,26 +203,26 @@ determineNotificationCandidates NotificationAllocationOutdatedRatings{..} =
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationExamOfficeExamResults{..} =
|
determineNotificationCandidates NotificationExamOfficeExamResults{..} =
|
||||||
E.select . E.from $ \user -> do
|
E.selectSource . E.from $ \user -> do
|
||||||
E.where_ . E.exists . E.from $ \examResult -> do
|
E.where_ . E.exists . E.from $ \examResult -> do
|
||||||
E.where_ $ examResult E.^. ExamResultExam E.==. E.val nExam
|
E.where_ $ examResult E.^. ExamResultExam E.==. E.val nExam
|
||||||
E.where_ $ examOfficeExamResultAuth (user E.^. UserId) examResult
|
E.where_ $ examOfficeExamResultAuth (user E.^. UserId) examResult
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationExamOfficeExamResultsChanged{..} =
|
determineNotificationCandidates NotificationExamOfficeExamResultsChanged{..} =
|
||||||
E.select . E.from $ \user -> do
|
E.selectSource . E.from $ \user -> do
|
||||||
E.where_ . E.exists . E.from $ \examResult -> do
|
E.where_ . E.exists . E.from $ \examResult -> do
|
||||||
E.where_ $ examResult E.^. ExamResultId `E.in_` E.valList (Set.toList nExamResults)
|
E.where_ $ examResult E.^. ExamResultId `E.in_` E.valList (Set.toList nExamResults)
|
||||||
E.where_ $ examOfficeExamResultAuth (user E.^. UserId) examResult
|
E.where_ $ examOfficeExamResultAuth (user E.^. UserId) examResult
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationExamOfficeExternalExamResults{..} =
|
determineNotificationCandidates NotificationExamOfficeExternalExamResults{..} =
|
||||||
E.select . E.from $ \user -> do
|
E.selectSource . E.from $ \user -> do
|
||||||
E.where_ . E.exists . E.from $ \externalExamResult -> do
|
E.where_ . E.exists . E.from $ \externalExamResult -> do
|
||||||
E.where_ $ externalExamResult E.^. ExternalExamResultExam E.==. E.val nExternalExam
|
E.where_ $ externalExamResult E.^. ExternalExamResultExam E.==. E.val nExternalExam
|
||||||
E.where_ $ examOfficeExternalExamResultAuth (user E.^. UserId) externalExamResult
|
E.where_ $ examOfficeExternalExamResultAuth (user E.^. UserId) externalExamResult
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates notif@NotificationAllocationResults{..} = do
|
determineNotificationCandidates notif@NotificationAllocationResults{..} = do
|
||||||
lastExec <- fmap (fmap $ cronLastExecTime . entityVal) . getBy . UniqueCronLastExec . toJSON $ JobQueueNotification notif
|
lastExec <- lift . fmap (fmap $ cronLastExecTime . entityVal) . getBy . UniqueCronLastExec . toJSON $ JobQueueNotification notif
|
||||||
E.select . E.from $ \user -> do
|
E.selectSource . E.from $ \user -> do
|
||||||
let isStudent = E.exists . E.from $ \application ->
|
let isStudent = E.exists . E.from $ \application ->
|
||||||
E.where_ $ application E.^. CourseApplicationAllocation E.==. E.just (E.val nAllocation)
|
E.where_ $ application E.^. CourseApplicationAllocation E.==. E.just (E.val nAllocation)
|
||||||
E.&&. application E.^. CourseApplicationUser E.==. user E.^. UserId
|
E.&&. application E.^. CourseApplicationUser E.==. user E.^. UserId
|
||||||
@ -248,17 +248,17 @@ determineNotificationCandidates notif@NotificationAllocationResults{..} = do
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationCourseRegistered{..} =
|
determineNotificationCandidates NotificationCourseRegistered{..} =
|
||||||
maybeToList <$> getEntity nUser
|
yieldMMany $ getEntity nUser
|
||||||
determineNotificationCandidates NotificationSubmissionEdited{..} =
|
determineNotificationCandidates NotificationSubmissionEdited{..} =
|
||||||
E.select . E.from $ \(user `E.InnerJoin` submissionUser) -> do
|
E.selectSource . E.from $ \(user `E.InnerJoin` submissionUser) -> do
|
||||||
E.on $ user E.^. UserId E.==. submissionUser E.^. SubmissionUserUser
|
E.on $ user E.^. UserId E.==. submissionUser E.^. SubmissionUserUser
|
||||||
E.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val nSubmission
|
E.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val nSubmission
|
||||||
E.&&. user E.^. UserId E.!=. E.val nInitiator
|
E.&&. user E.^. UserId E.!=. E.val nInitiator
|
||||||
return user
|
return user
|
||||||
determineNotificationCandidates NotificationSubmissionUserCreated{..} =
|
determineNotificationCandidates NotificationSubmissionUserCreated{..} =
|
||||||
maybeToList <$> getEntity nUser
|
yieldMMany $ getEntity nUser
|
||||||
determineNotificationCandidates NotificationSubmissionUserDeleted{..} =
|
determineNotificationCandidates NotificationSubmissionUserDeleted{..} =
|
||||||
maybeToList <$> getEntity nUser
|
yieldMMany $ getEntity nUser
|
||||||
|
|
||||||
|
|
||||||
classifyNotification :: Notification -> DB NotificationTrigger
|
classifyNotification :: Notification -> DB NotificationTrigger
|
||||||
|
|||||||
@ -43,7 +43,8 @@ import qualified Data.List as List
|
|||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
import qualified Data.Vector as V
|
import qualified Data.Vector as V
|
||||||
|
|
||||||
import qualified Data.Conduit.List as C
|
-- import qualified Data.Conduit.List as C
|
||||||
|
import qualified Data.Conduit.Combinators as C
|
||||||
|
|
||||||
import Control.Lens
|
import Control.Lens
|
||||||
import Control.Lens as Utils (none)
|
import Control.Lens as Utils (none)
|
||||||
@ -815,6 +816,9 @@ anyMC, allMC :: forall a o m. Monad m => (a -> m Bool) -> ConduitT a o m Bool
|
|||||||
anyMC f = C.mapM f .| orC
|
anyMC f = C.mapM f .| orC
|
||||||
allMC f = C.mapM f .| andC
|
allMC f = C.mapM f .| andC
|
||||||
|
|
||||||
|
yieldMMany :: forall mono m a. (Monad m, MonoFoldable mono) => m mono -> ConduitT a (Element mono) m ()
|
||||||
|
yieldMMany = C.yieldMany <=< lift
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
-- Alternative --
|
-- Alternative --
|
||||||
-----------------
|
-----------------
|
||||||
|
|||||||
@ -819,8 +819,8 @@ fillDb = do
|
|||||||
, sheetVisibleFrom = Just $ termTime True Summer prog False Monday toMidnight
|
, sheetVisibleFrom = Just $ termTime True Summer prog False Monday toMidnight
|
||||||
, sheetActiveFrom = Just $ termTime True Summer (prog + 1) False Monday toMidnight
|
, sheetActiveFrom = Just $ termTime True Summer (prog + 1) False Monday toMidnight
|
||||||
, sheetActiveTo = Just $ termTime True Summer (prog + 2) False Sunday beforeMidnight
|
, sheetActiveTo = Just $ termTime True Summer (prog + 2) False Sunday beforeMidnight
|
||||||
, sheetHintFrom = Nothing
|
, sheetHintFrom = Just $ termTime True Summer (prog + 1) False Sunday beforeMidnight
|
||||||
, sheetSolutionFrom = Nothing
|
, sheetSolutionFrom = Just $ termTime True Summer (prog + 2) False Sunday beforeMidnight
|
||||||
, sheetAutoDistribute = True
|
, sheetAutoDistribute = True
|
||||||
, sheetAnonymousCorrection = True
|
, sheetAnonymousCorrection = True
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user