chore(lms): rethunk qualifcation model and process
This commit is contained in:
parent
3d3ac9d77c
commit
3656f1e6f1
@ -3,52 +3,99 @@ Qualification
|
||||
shorthand (CI Text)
|
||||
name (CI Text)
|
||||
description StoredMarkup Maybe -- user-defined large Html, ought to contain full description
|
||||
validDuration Word Maybe -- qualification is valid for this number of months
|
||||
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 -- refresher is scheduled within this number of month before expiry
|
||||
elearningOnly Bool -- successful E-learing automatically increases validity
|
||||
-- refreshInvitation StoredMarkup -- hard-coded I18N-MSGs used instead, but displayed on qualification page
|
||||
-- expiryNotification StoredMarkup Maybe -- configurable user-profile-notifcations are used instead
|
||||
refreshWithin CalendarDiffDays Maybe -- automatically schedule e-refresher within this number of month/days before expiry
|
||||
-- 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!
|
||||
UniqueSchoolShort school shorthand -- must be unique per school and shorthand
|
||||
UniqueSchoolName school name -- must be unique per school and name
|
||||
deriving Generic
|
||||
|
||||
-- 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?
|
||||
-- - 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)
|
||||
|
||||
QualificationPrecondition
|
||||
qualification QualificationId -- AND: not unique, ie. qualification can have multiple required preconditions
|
||||
required [QualificationId] -- OR : alternatives, any one will suffice
|
||||
continuous Bool -- expiring precondition removes qualification
|
||||
deriving Generic
|
||||
|
||||
-- TODO: connect Qualification with Exams!
|
||||
|
||||
QualificationEdit
|
||||
user User
|
||||
time UTCTime
|
||||
qualification QualificationId OnDeleteCascade OnUpdateCascade
|
||||
deriving Generic
|
||||
|
||||
-- TODO: connect Qualification with Exams!
|
||||
|
||||
QualificationUser
|
||||
user User
|
||||
qualification QualificationId
|
||||
qualification QualificationId OnDeleteCascade OnUpdateCascade
|
||||
validUntil UTCTime
|
||||
lastRefresh UTCTime -- lastRefresh > validUntil possible, if Qualification^elearningOnly == False
|
||||
firstHeld UTCTime -- first time the qualification was earned, should never change
|
||||
UniqueQualificationUser qualification user
|
||||
deriving Generic
|
||||
|
||||
-- LMS Interface Tables, need regular processing by background jobs, per QualificationId:
|
||||
--
|
||||
-- 1. Daily Job: Add to LmsUser daily all qualification holders with
|
||||
-- 0 <= QualificationUserValidUntil - now < QualificationRefreshWithin (time to schedule refresher)
|
||||
-- /\ now - max(LmsUserStarted) > QualificationRefreshWithin (not already enlisted; Problem: QualificationELearningOnly!)
|
||||
-- generate fresh ident and pin. (Bools?)
|
||||
--
|
||||
-- 2. REST GET User.csv:
|
||||
-- - where LmsUserReceived == Nothing \/ (LmsUserResetPin /\ LmsUserEnded == Nothing)
|
||||
-- - delete-flag: isJust LmsUserSuccess
|
||||
-- Note: REST means that LmsUserResetPin and LmsUserDelete remain unchanged by this GET request!
|
||||
--
|
||||
-- 3. REST POST Userlist.csv:
|
||||
-- -- save as is to LmsUserlist
|
||||
-- -- change LmsUserEnded from Nothing to Just now, if not included in received list
|
||||
--
|
||||
-- 4. REST POST Ergebnisse.csv: just save as is to LmsResult
|
||||
--
|
||||
-- 5. Daily Job LmsUserlist: -- Note: containment needs at-once processing
|
||||
-- - For all LmsUser:
|
||||
-- + if contained, set LmsUserReceived to Just now()
|
||||
-- + otherwise, set LmsUserEnded to Just now()
|
||||
-- - if LmsUserlistFailed:
|
||||
-- + set LmsUserSuccess to Just False
|
||||
-- + set LmsUserDelete to True
|
||||
-- - move row to LmsAudit
|
||||
--
|
||||
-- 6. Daily Job LmsResult:
|
||||
-- - set LmsUserReceived to Just now()
|
||||
-- - set LmsUserSuccess to Just True
|
||||
-- - move row to LmsAudit
|
||||
|
||||
|
||||
-- LMS Interface Tables, need regular processing by background jobs
|
||||
LmsUser
|
||||
qualification QualificationId
|
||||
qualification QualificationId OnDeleteCascade OnUpdateCascade
|
||||
user UserId
|
||||
ident LmsIdent
|
||||
pin Text
|
||||
resetPin Bool -- should the pin be reset?
|
||||
delete Bool -- should the ident be deleted? TODO: do we need this?
|
||||
started UTCTime Maybe
|
||||
submitted UTCTime Maybe -- ident was sent to LMS (should happen only once)
|
||||
ended UTCTime Maybe -- ident was deleted in LMS
|
||||
resetPin Bool default=false -- should pin be reset?
|
||||
success Bool Maybe -- open, success or failure; isJust indicates user will be deleted from LMS
|
||||
-- success LmsNotification --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
|
||||
qualification QualificationId
|
||||
qualification QualificationId OnDeleteCascade OnUpdateCascade
|
||||
ident LmsIdent
|
||||
failed Bool
|
||||
timestamp UTCTime default=now()
|
||||
@ -56,7 +103,7 @@ LmsUserlist
|
||||
|
||||
-- LmsUserlist stores LMS upload ofr later processing only
|
||||
LmsResult
|
||||
qualification QualificationId
|
||||
qualification QualificationId OnDeleteCascade OnUpdateCascade
|
||||
ident LmsIdent
|
||||
success Day
|
||||
timestamp UTCTime default=now()
|
||||
@ -66,7 +113,7 @@ LmsResult
|
||||
LmsAudit
|
||||
qualification QualificationId
|
||||
ident LmsIdent
|
||||
notificationType LmsNotification
|
||||
received UTCTime
|
||||
notificationType LmsNotification
|
||||
received UTCTime -- timestamp from LmsUserlist/LmsResult
|
||||
processed UTCTime default=now()
|
||||
deriving Generic
|
||||
|
||||
@ -18,7 +18,8 @@ newtype LmsIdent = LmsIdent { getLmsIdent :: Text }
|
||||
|
||||
makeLenses_ ''LmsIdent
|
||||
|
||||
data LmsNotification = LmsAlive | LmsBlocked | LmsSuccesss Day
|
||||
-- TODO: is this a good idea? Maybe just an ordinary Enum and a separate Day Column in the DB would be better, especially since LmsBlocked should really also encode a Day
|
||||
data LmsNotification = LmsOpen | LmsBlocked | LmsSuccess Day
|
||||
deriving (Eq, Ord, Read, Show, Generic, Typeable, NFData)
|
||||
|
||||
deriveJSON defaultOptions
|
||||
|
||||
Loading…
Reference in New Issue
Block a user