diff --git a/models/lms.model b/models/lms.model index 4b369a48e..900128696 100644 --- a/models/lms.model +++ b/models/lms.model @@ -6,6 +6,7 @@ Qualification validDuration Word Maybe -- qualification is valid for this number of months or indefinitely auditDuration Word Maybe -- number of month to keep audit log refreshWithin CalendarDiffDays Maybe -- automatically schedule e-refresher within this number of month/days before expiry + elearningStart Bool -- automatically schedule e-refresher -- elearningOnly Bool -- successful E-learing automatically increases validity. NO! -- refreshInvitation StoredMarkup -- hard-coded I18N-MSGs used instead, but displayed on qualification page NO! -- expiryNotification StoredMarkup Maybe -- configurable user-profile-notifcations are used instead NO! @@ -16,12 +17,17 @@ Qualification -- TODOs: -- - Enstehen Kosten, wenn Teilnehmer für KnowHow eingereiht werden, aber nicht am Kurs teilnehmen? -- Falls ja, so sollte bei automatischem refresher vorher der Kunde durch FRADrive befragt werden?! --- - Aufteilung Qualification "R" in zwei Teile: "R e-learning" und "R exam" okay? +-- A: Der Inhaber per Email informieren! +-- A: Es kann gleich eine LMS Pin generiert und verschickt werden! +-- - Aufteilung Qualification "R" in zwei Teile: "R e-learning" und "R praxis" okay? + +-- Fragen an Know-How: -- - Bedeutung LMS Übermittlung interner Mitarbeiter? -- - LmsUser shall submit DELTA only: Beware, GET Request will always return the same; until POST Request was processed! -- - Success/Failure: is an explicit LMS-delete still necessary? -- - User: pin reset = 1 to existing pin problematic? Resubmission of existing users with pin causes which problems? -- - ident unique for all qualifications F/R or duplicated? (F/R refreshers might be simultaneous) +-- - Anzahl Fehlversuche: wird pro Durchfallen ein Failed gemeldet oder nur einmal? QualificationPrecondition qualification QualificationId -- AND: not unique, ie. qualification can have multiple required preconditions @@ -43,6 +49,8 @@ QualificationUser validUntil UTCTime lastRefresh UTCTime -- lastRefresh > validUntil possible, if Qualification^elearningOnly == False firstHeld UTCTime -- first time the qualification was earned, should never change + -- temporärer Entzug vorsehen + -- Begründungsfeld vorsehen UniqueQualificationUser qualification user deriving Generic @@ -86,14 +94,14 @@ LmsUser pin Text resetPin Bool default=false -- should pin be reset? success Bool Maybe -- open, success or failure; isJust indicates user will be deleted from LMS - -- success LmsStatus --this would also encode Day information?! + -- success LmsStatus -- this would also encode Day information?! started UTCTime default=now() received UTCTime Maybe -- last acknowledgement by LMS ended UTCTime Maybe -- ident was deleted from LMS UniqueLmsUser qualification ident deriving Generic --- LmsUserlist stores LMS upload ofr later processing only +-- LmsUserlist stores LMS upload for later processing only LmsUserlist qualification QualificationId OnDeleteCascade OnUpdateCascade ident LmsIdent @@ -101,7 +109,7 @@ LmsUserlist timestamp UTCTime default=now() deriving Generic --- LmsUserlist stores LMS upload ofr later processing only +-- LmsResult stores LMS upload for later processing only LmsResult qualification QualificationId OnDeleteCascade OnUpdateCascade ident LmsIdent @@ -113,7 +121,7 @@ LmsResult LmsAudit qualification QualificationId ident LmsIdent - notificationType LmsStatus + notificationType LmsStatus -- LmsOpen | LmsBlocked | LmsSuccess Day received UTCTime -- timestamp from LmsUserlist/LmsResult processed UTCTime default=now() deriving Generic diff --git a/src/Handler/LMS/Result.hs b/src/Handler/LMS/Result.hs index bbd7d1dd1..350abfdf3 100644 --- a/src/Handler/LMS/Result.hs +++ b/src/Handler/LMS/Result.hs @@ -142,7 +142,25 @@ mkResultTable qid = do dbtIdent :: Text dbtIdent = "lms-userlist" dbtCsvEncode = noCsvEncode - dbtCsvDecode = Nothing -- TODO !!! continue here !!! CSV Import is the purpose of this page! Just save to DB, create Job to deal with it later! + dbtCsvDecode = Nothing {- + dbtCsvDecode = Just DBTCsvDecode -- Just save to DB; Job will process data later + { dbtCsvRowKey = const $ return Nothing -- always generate a fres key, or should we use ident? + , dbtCsvComputeActions = \case + DBCsvDiffMissing{} + -> return () -- no deletion + DBCsvDiffExisting{} + -> return () -- no deletion + DBCsvDiffNew{dbCsvNewKey, dbCsvNew} + -> _insert + , dbtCsvClassifyAction = const () -- there is only one action: insert into table + , dbtCsvCoarsenActionClass = const () -- there is only one action: insert into table + , dbtCsvValidateActions = return () -- no validation, since this is an automatic upload, i.e. no user to review error + , dbtCsvExecuteActions = _savetodb + , dbtCsvRenderKey = _renderKey -- what is the purpose? + , dbtCsvRenderActionClass = _renderActioCalss -- what is the purpose? + , dbtCsvRenderException = _renderException + } + -} dbtExtraReps = [] resultDBTableValidator = def diff --git a/src/Utils.hs b/src/Utils.hs index d2aabe9ae..886c45a0d 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -1017,7 +1017,7 @@ mapMM_ f mxs = Fold.mapM_ f =<< mxs forMM_ :: (Foldable t, Monad m) => m (t a) -> (a -> m ()) -> m () forMM_ = flip mapMM_ --- is this a good idea? can we generalise this pattern? +-- | Monadic bind that also returns the intermediate value. This common pattern avoids the duplicated local identifiers required in the equivalent do-notation. bind2 :: Monad m => m a -> (a -> m b) -> m (a, b) bind2 ma ma2b = do a <- ma