diff --git a/src/Jobs/Crontab.hs b/src/Jobs/Crontab.hs index 6605f42d5..aebc11ad1 100644 --- a/src/Jobs/Crontab.hs +++ b/src/Jobs/Crontab.hs @@ -162,54 +162,57 @@ determineCrontab = execWriterT $ do let sheetJobs (Entity nSheet Sheet{..}) = do - for_ sheetActiveFrom $ \aFrom -> + for_ (max <$> sheetVisibleFrom <*> sheetActiveFrom) $ \aFrom -> tell $ HashMap.singleton (JobCtlQueue $ JobQueueNotification NotificationSheetActive{..}) Cron - { cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom aFrom - , cronRepeat = CronRepeatOnChange + { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ aFrom + , cronRepeat = CronRepeatNever , cronRateLimit = appNotificationRateLimit , 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 + 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] tell $ HashMap.singleton (JobCtlQueue $ JobQueueNotification NotificationSheetHint{..}) Cron - { cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom hFrom - , cronRepeat = CronRepeatOnChange + { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ hFrom + , cronRepeat = CronRepeatNever , cronRateLimit = appNotificationRateLimit - , cronNotAfter = Left appNotificationExpiration + , cronNotAfter = maybe (Left appNotificationExpiration) (Right . CronTimestamp . utcToLocalTimeTZ appTZ) sheetActiveTo } - for_ sheetSolutionFrom $ \hFrom -> maybeT (return ()) $ do - guard $ maybe True (\aFrom -> abs (diffUTCTime aFrom hFrom) > 300) sheetActiveFrom + for_ (max <$> sheetVisibleFrom <*> sheetSolutionFrom) $ \sFrom -> maybeT (return ()) $ do + guard $ maybe True (\aFrom -> abs (diffUTCTime aFrom sFrom) > 300) sheetActiveFrom guardM . lift . lift $ exists [SheetFileType ==. SheetSolution, SheetFileSheet ==. nSheet] tell $ HashMap.singleton (JobCtlQueue $ JobQueueNotification NotificationSheetSolution{..}) Cron - { cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom hFrom - , cronRepeat = CronRepeatOnChange + { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ sFrom + , cronRepeat = CronRepeatNever , cronRateLimit = appNotificationRateLimit - , cronNotAfter = Left appNotificationExpiration + , cronNotAfter = Left nominalDay } for_ sheetActiveTo $ \aTo -> do - tell $ HashMap.singleton - (JobCtlQueue $ JobQueueNotification NotificationSheetSoonInactive{..}) - Cron - { cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ . maybe id max sheetActiveFrom . maybe id max sheetVisibleFrom $ addUTCTime (-nominalDay) aTo - , cronRepeat = CronRepeatOnChange -- Allow repetition of the notification (if something changes), but wait at least an hour - , cronRateLimit = appNotificationRateLimit - , cronNotAfter = Right . CronTimestamp $ utcToLocalTimeTZ appTZ aTo - } - tell $ HashMap.singleton - (JobCtlQueue $ JobQueueNotification NotificationSheetInactive{..}) - Cron - { cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ $ maybe id max sheetVisibleFrom aTo - , cronRepeat = CronRepeatOnChange - , cronRateLimit = appNotificationRateLimit - , cronNotAfter = Left appNotificationExpiration - } + whenIsJust (max aTo <$> sheetVisibleFrom) $ \aTo' -> do + tell $ HashMap.singleton + (JobCtlQueue $ JobQueueNotification NotificationSheetSoonInactive{..}) + Cron + { cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ . maybe id max sheetActiveFrom $ addUTCTime (-nominalDay) aTo' + , cronRepeat = CronRepeatOnChange -- Allow repetition of the notification (if something changes), but wait at least an hour + , cronRateLimit = appNotificationRateLimit + , cronNotAfter = Right . CronTimestamp $ utcToLocalTimeTZ appTZ aTo + } + tell $ HashMap.singleton + (JobCtlQueue $ JobQueueNotification NotificationSheetInactive{..}) + Cron + { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ aTo + , cronRepeat = CronRepeatOnChange + , cronRateLimit = appNotificationRateLimit + , cronNotAfter = Left appNotificationExpiration + } when sheetAutoDistribute $ tell $ HashMap.singleton (JobCtlQueue $ JobDistributeCorrections nSheet) diff --git a/src/Jobs/Handler/QueueNotification.hs b/src/Jobs/Handler/QueueNotification.hs index 11d3d15d0..29b078816 100644 --- a/src/Jobs/Handler/QueueNotification.hs +++ b/src/Jobs/Handler/QueueNotification.hs @@ -15,82 +15,82 @@ import qualified Data.Set as Set import Handler.Utils.ExamOffice.Exam import Handler.Utils.ExamOffice.ExternalExam +import qualified Data.Conduit.Combinators as C + dispatchJobQueueNotification :: Notification -> JobHandler UniWorX dispatchJobQueueNotification jNotification = JobHandlerAtomic $ do - candidates <- hoist lift $ determineNotificationCandidates jNotification nClass <- hoist lift $ classifyNotification jNotification - mapM_ (queueDBJob . flip JobSendNotification jNotification) $ do - Entity uid User{userNotificationSettings} <- candidates - guard $ notificationAllowed userNotificationSettings nClass - return uid + runConduit $ transPipe (hoist lift) (determineNotificationCandidates jNotification) + .| C.filter (\(Entity _ User{userNotificationSettings}) -> notificationAllowed userNotificationSettings nClass) + .| C.map (flip JobSendNotification jNotification . entityKey) .| sinkDBJobs -determineNotificationCandidates :: Notification -> DB [Entity User] +determineNotificationCandidates :: Notification -> ConduitT () (Entity User) DB () 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.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val nSubmission return user 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 $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive E.where_ $ sheet E.^. SheetId E.==. E.val nSheet return user 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 $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive E.where_ $ sheet E.^. SheetId E.==. E.val nSheet return user 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 $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive E.where_ $ sheet E.^. SheetId E.==. E.val nSheet return user 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 $ user E.^. UserId E.==. courseParticipant E.^. CourseParticipantUser E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive E.where_ $ sheet E.^. SheetId E.==. E.val nSheet return user 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.^. LecturerUser E.==. user E.^. UserId E.where_ $ sheet E.^. SheetId E.==. E.val nSheet return user determineNotificationCandidates NotificationCorrectionsAssigned{..} - = selectList [UserId ==. nUser] [] + = selectSource [UserId ==. nUser] [] 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.^. LecturerUser E.==. user E.^. UserId E.where_ $ sheet E.^. SheetId E.==. E.val nSheet return user determineNotificationCandidates NotificationUserRightsUpdate{..} = do -- 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 - 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 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.where_ $ admin E.^. UserFunctionSchool `E.in_` E.valList (Set.toList newAdminSchools) E.&&. admin E.^. UserFunctionFunction E.==. E.val SchoolAdmin return user - return . nub $ affectedUser <> affectedAdmins + yieldMany . nub $ affectedUser <> affectedAdmins determineNotificationCandidates NotificationUserAuthModeUpdate{..} - = selectList [UserId ==. nUser] [] + = selectSource [UserId ==. nUser] [] 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.^. CourseParticipantCourse E.==. exam E.^. ExamCourse E.where_ $ exam E.^. ExamId E.==. E.val nExam @@ -100,7 +100,7 @@ determineNotificationCandidates NotificationExamRegistrationActive{..} = E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive return user 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.^. CourseParticipantCourse E.==. exam E.^. ExamCourse E.where_ $ exam E.^. ExamId E.==. E.val nExam @@ -110,21 +110,21 @@ determineNotificationCandidates NotificationExamRegistrationSoonInactive{..} = E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive return user 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.where_ $ examRegistration E.^. ExamRegistrationExam E.==. E.val nExam return user determineNotificationCandidates notif@NotificationExamResult{..} = do - lastExec <- 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 + lastExec <- lift . fmap (fmap $ cronLastExecTime . entityVal) . getBy . UniqueCronLastExec . toJSON $ JobQueueNotification notif + 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.where_ $ examResult E.^. ExamResultExam E.==. E.val nExam whenIsJust lastExec $ \lastExec' -> E.where_ $ examResult E.^. ExamResultLastChanged E.>. E.val lastExec' return user determineNotificationCandidates NotificationAllocationStaffRegister{..} = do - Allocation{..} <- getJust nAllocation - E.select . E.from $ \(user `E.InnerJoin` userFunction) -> E.distinctOnOrderBy [E.asc $ user E.^. UserId] $ do + Allocation{..} <- lift $ getJust nAllocation + 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.&&. userFunction E.^. UserFunctionSchool E.==. E.val allocationSchool E.&&. userFunction E.^. UserFunctionFunction E.==. E.val SchoolLecturer @@ -143,7 +143,7 @@ determineNotificationCandidates NotificationAllocationStaffRegister{..} = do return user 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.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse @@ -162,7 +162,7 @@ determineNotificationCandidates NotificationAllocationAllocation{..} = return user 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.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse @@ -176,8 +176,8 @@ determineNotificationCandidates NotificationAllocationUnratedApplications{..} = return user determineNotificationCandidates NotificationAllocationRegister{..} = do - Allocation{..} <- getJust nAllocation - E.select . E.from $ \user -> do + Allocation{..} <- lift $ getJust nAllocation + E.selectSource . E.from $ \user -> do E.where_ . E.exists . E.from $ \userSchool -> E.where_ $ userSchool E.^. UserSchoolUser E.==. user E.^. UserId E.&&. userSchool E.^. UserSchoolSchool E.==. E.val allocationSchool @@ -189,7 +189,7 @@ determineNotificationCandidates NotificationAllocationRegister{..} = do return user 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.&&. allocationCourse E.^. AllocationCourseAllocation E.==. E.val nAllocation E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse @@ -203,26 +203,26 @@ determineNotificationCandidates NotificationAllocationOutdatedRatings{..} = return user determineNotificationCandidates NotificationExamOfficeExamResults{..} = - E.select . E.from $ \user -> do + E.selectSource . E.from $ \user -> do E.where_ . E.exists . E.from $ \examResult -> do E.where_ $ examResult E.^. ExamResultExam E.==. E.val nExam E.where_ $ examOfficeExamResultAuth (user E.^. UserId) examResult return user determineNotificationCandidates NotificationExamOfficeExamResultsChanged{..} = - E.select . E.from $ \user -> do + E.selectSource . E.from $ \user -> do E.where_ . E.exists . E.from $ \examResult -> do E.where_ $ examResult E.^. ExamResultId `E.in_` E.valList (Set.toList nExamResults) E.where_ $ examOfficeExamResultAuth (user E.^. UserId) examResult return user determineNotificationCandidates NotificationExamOfficeExternalExamResults{..} = - E.select . E.from $ \user -> do + E.selectSource . E.from $ \user -> do E.where_ . E.exists . E.from $ \externalExamResult -> do E.where_ $ externalExamResult E.^. ExternalExamResultExam E.==. E.val nExternalExam E.where_ $ examOfficeExternalExamResultAuth (user E.^. UserId) externalExamResult return user determineNotificationCandidates notif@NotificationAllocationResults{..} = do - lastExec <- fmap (fmap $ cronLastExecTime . entityVal) . getBy . UniqueCronLastExec . toJSON $ JobQueueNotification notif - E.select . E.from $ \user -> do + lastExec <- lift . fmap (fmap $ cronLastExecTime . entityVal) . getBy . UniqueCronLastExec . toJSON $ JobQueueNotification notif + E.selectSource . E.from $ \user -> do let isStudent = E.exists . E.from $ \application -> E.where_ $ application E.^. CourseApplicationAllocation E.==. E.just (E.val nAllocation) E.&&. application E.^. CourseApplicationUser E.==. user E.^. UserId @@ -248,17 +248,17 @@ determineNotificationCandidates notif@NotificationAllocationResults{..} = do return user determineNotificationCandidates NotificationCourseRegistered{..} = - maybeToList <$> getEntity nUser + yieldMMany $ getEntity nUser 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.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val nSubmission E.&&. user E.^. UserId E.!=. E.val nInitiator return user determineNotificationCandidates NotificationSubmissionUserCreated{..} = - maybeToList <$> getEntity nUser + yieldMMany $ getEntity nUser determineNotificationCandidates NotificationSubmissionUserDeleted{..} = - maybeToList <$> getEntity nUser + yieldMMany $ getEntity nUser classifyNotification :: Notification -> DB NotificationTrigger diff --git a/src/Utils.hs b/src/Utils.hs index da20821a1..94b1b4426 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -43,7 +43,8 @@ import qualified Data.List as List import qualified Data.HashMap.Strict as HashMap 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 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 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 -- ----------------- diff --git a/test/Database/Fill.hs b/test/Database/Fill.hs index d70a39306..6e5f2ac55 100644 --- a/test/Database/Fill.hs +++ b/test/Database/Fill.hs @@ -819,8 +819,8 @@ fillDb = do , sheetVisibleFrom = Just $ termTime True Summer prog False Monday toMidnight , sheetActiveFrom = Just $ termTime True Summer (prog + 1) False Monday toMidnight , sheetActiveTo = Just $ termTime True Summer (prog + 2) False Sunday beforeMidnight - , sheetHintFrom = Nothing - , sheetSolutionFrom = Nothing + , sheetHintFrom = Just $ termTime True Summer (prog + 1) False Sunday beforeMidnight + , sheetSolutionFrom = Just $ termTime True Summer (prog + 2) False Sunday beforeMidnight , sheetAutoDistribute = True , sheetAnonymousCorrection = True }