Qualification school SchoolId --TODO: Ansprechpartner der Schule in Briefe erwähnen 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 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! 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?! -- 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 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 QualificationUser user User 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 -- temporärer Entzug vorsehen -- Begründungsfeld vorsehen 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 LmsUser qualification QualificationId OnDeleteCascade OnUpdateCascade user UserId ident LmsIdent -- must be unique accross all LMS courses! 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?! --toDelete encoded by Handler.Utils.LMS.lmsUserToDelete 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 for later processing only LmsUserlist qualification QualificationId OnDeleteCascade OnUpdateCascade ident LmsIdent failed Bool timestamp UTCTime default=now() UniqueLmsUserlist qualification ident deriving Generic -- LmsResult stores LMS upload for later processing only LmsResult qualification QualificationId OnDeleteCascade OnUpdateCascade ident LmsIdent success Day timestamp UTCTime default=now() UniqueLmsResult qualification ident success -- required by DBTable deriving Generic -- Logs all processed rows from LmsUserlist and LmsResult LmsAudit qualification QualificationId ident LmsIdent notificationType LmsStatus -- LmsOpen | LmsBlocked | LmsSuccess Day received UTCTime -- timestamp from LmsUserlist/LmsResult processed UTCTime default=now() deriving Generic