module Utils.Sheet where import Import.NoFoundation import qualified Database.Esqueleto as E import Database.Esqueleto.Internal.Language (From) -- cannot be avoided here -- DB Queries for Sheets that are used in several places sheetCurrent :: MonadIO m => TermId -> SchoolId -> CourseShorthand -> SqlReadT m (Maybe SheetName) sheetCurrent tid ssh csh = do now <- liftIO getCurrentTime sheets <- E.select . E.from $ \(course `E.InnerJoin` sheet) -> do E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId E.where_ $ sheet E.^. SheetActiveTo E.>. E.val now E.&&. sheet E.^. SheetActiveFrom E.<=. E.val now E.&&. course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh E.&&. course E.^. CourseShorthand E.==. E.val csh E.orderBy [E.asc $ sheet E.^. SheetActiveTo] E.limit 1 return $ sheet E.^. SheetName return $ case sheets of [] -> Nothing [E.Value shn] -> Just shn _ -> error "SQL Query with limit 1 returned more than one result" sheetOldUnassigned :: MonadIO m => TermId -> SchoolId -> CourseShorthand -> SqlReadT m (Maybe SheetName) sheetOldUnassigned tid ssh csh = do now <- liftIO getCurrentTime sheets <- E.select . E.from $ \(course `E.InnerJoin` sheet) -> do E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId E.where_ $ sheet E.^. SheetActiveTo E.<=. E.val now E.&&. course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh E.&&. course E.^. CourseShorthand E.==. E.val csh E.where_ . E.exists . E.from $ \submission -> E.where_ $ submission E.^. SubmissionSheet E.==. sheet E.^. SheetId E.&&. E.isNothing (submission E.^. SubmissionRatingBy) E.orderBy [E.asc $ sheet E.^. SheetActiveTo] E.limit 1 return $ sheet E.^. SheetName return $ case sheets of [] -> Nothing [E.Value shn] -> Just shn _ -> error "SQL Query with limit 1 returned more than one result" -- | Return a specfic file from a `Sheet` sheetFileQuery :: MonadResource m => TermId -> SchoolId -> CourseShorthand -> SheetName -> SheetFileType -> FilePath -> Source (SqlPersistT m) (Entity File) sheetFileQuery tid ssh csh shn sft title = E.selectSource $ E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` sFile `E.InnerJoin` file) -> do -- Restrict to consistent rows that correspond to each other E.on (file E.^. FileId E.==. sFile E.^. SheetFileFile) E.on (sFile E.^. SheetFileSheet E.==. sheet E.^. SheetId) E.on (sheet E.^. SheetCourse E.==. course E.^. CourseId) -- filter to requested file E.where_ ((file E.^. FileTitle E.==. E.val title) E.&&. (sFile E.^. SheetFileType E.==. E.val sft ) E.&&. (sheet E.^. SheetName E.==. E.val shn ) E.&&. (course E.^. CourseShorthand E.==. E.val csh ) E.&&. (course E.^. CourseSchool E.==. E.val ssh ) E.&&. (course E.^. CourseTerm E.==. E.val tid ) ) -- return file entity return file -- | Return all files of a certain `SheetFileType` for a `Sheet` sheetFilesAllQuery :: MonadResource m => TermId -> SchoolId -> CourseShorthand -> SheetName -> SheetFileType -> Source (SqlPersistT m) (Entity File) sheetFilesAllQuery tid ssh csh shn sft = E.selectSource $ E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` sFile `E.InnerJoin` file) -> do -- Restrict to consistent rows that correspond to each other E.on (file E.^. FileId E.==. sFile E.^. SheetFileFile) E.on (sFile E.^. SheetFileSheet E.==. sheet E.^. SheetId) E.on (sheet E.^. SheetCourse E.==. course E.^. CourseId) -- filter to requested file E.where_ ((sheet E.^. SheetName E.==. E.val shn ) E.&&. (course E.^. CourseShorthand E.==. E.val csh ) E.&&. (course E.^. CourseSchool E.==. E.val ssh ) E.&&. (course E.^. CourseTerm E.==. E.val tid ) E.&&. (sFile E.^. SheetFileType E.==. E.val sft ) ) -- return file entity return file -- | Return all files of certain `SheetFileTypes` for a `Sheet` sheetFilesSFTsQuery :: MonadResource m => TermId -> SchoolId -> CourseShorthand -> SheetName -> [SheetFileType] -> Source (SqlPersistT m) (Entity File) sheetFilesSFTsQuery tid ssh csh shn sfts = E.selectSource $ E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` sFile `E.InnerJoin` file) -> do -- Restrict to consistent rows that correspond to each other E.on (file E.^. FileId E.==. sFile E.^. SheetFileFile) E.on (sFile E.^. SheetFileSheet E.==. sheet E.^. SheetId) E.on (sheet E.^. SheetCourse E.==. course E.^. CourseId) -- filter to requested file E.where_ ((sheet E.^. SheetName E.==. E.val shn ) E.&&. (course E.^. CourseShorthand E.==. E.val csh ) E.&&. (course E.^. CourseSchool E.==. E.val ssh ) E.&&. (course E.^. CourseTerm E.==. E.val tid ) E.&&. (sFile E.^. SheetFileType `E.in_` E.valList sfts ) ) -- return file entity return file -- | Check whether a sheet has any files for a given file type hasSheetFileQuery :: Database.Esqueleto.Internal.Language.From query expr backend (expr (Entity SheetFile)) => expr (Entity Sheet) -> SheetFileType -> expr (E.Value Bool) hasSheetFileQuery sheet sft = E.exists $ E.from $ \sFile -> E.where_ ((sFile E.^. SheetFileSheet E.==. sheet E.^. SheetId) E.&&. (sFile E.^. SheetFileType E.==. E.val sft ))