chore(lms): add action to manually enqueue qual holder for e-learning

This commit is contained in:
Steffen Jost 2024-06-27 16:29:25 +02:00
parent 37efc89e07
commit e25a8569c5
6 changed files with 174 additions and 153 deletions

View File

@ -107,6 +107,8 @@ QualificationActUnblock: Entzug aufheben
QualificationActRenew: Qualifikation regulär verlängern QualificationActRenew: Qualifikation regulär verlängern
QualificationActGrant: Qualifikation vergeben QualificationActGrant: Qualifikation vergeben
QualificationActGrantWarning: Diese Funktion ist nur für seltene Ausnahmefälle vorgesehen! Ein Entzug wird ggf. aufgehoben. QualificationActGrantWarning: Diese Funktion ist nur für seltene Ausnahmefälle vorgesehen! Ein Entzug wird ggf. aufgehoben.
QualificationActStartELearning: ELearning für gültige Inhaber (neu) starten
QualificationActStartELearningStatus l@QualificationShorthand n@Int m@Int: ELearning #{l} für #{n}/#{m} Teilnehmer (neu) gestartet. Hinweis: Es kann länger dauern, bis das LMS tatsächlich startet.
QualificationStatusBlock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} entzogen QualificationStatusBlock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} entzogen
QualificationStatusUnblock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} reaktiviert QualificationStatusUnblock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} reaktiviert
LmsInactive: Aktuell kein ELearning aktiv LmsInactive: Aktuell kein ELearning aktiv
@ -120,7 +122,7 @@ LmsActReset: ELearning Fehlversuche zurücksetzen und entsperren
LmsActResetInfo: ELearning Login, Passwort und Fortschritt bleiben unverändert, eine neue Benachrichtigung ist nicht notwendig. Nur möglich für bereits gesperrte Lerner. Es kann bis zu 2 Stunden dauern, bis das LMS die Anfrage umgesetzt hat. LmsActResetInfo: ELearning Login, Passwort und Fortschritt bleiben unverändert, eine neue Benachrichtigung ist nicht notwendig. Nur möglich für bereits gesperrte Lerner. Es kann bis zu 2 Stunden dauern, bis das LMS die Anfrage umgesetzt hat.
LmsActResetFeedback n@Int m@Int: Für #{n}/#{m} ELearning Nutzer wurden alle Fehlversuche zurückgesetzt. LmsActResetFeedback n@Int m@Int: Für #{n}/#{m} ELearning Nutzer wurden alle Fehlversuche zurückgesetzt.
LmsActRestart: ELearning komplett neu starten LmsActRestart: ELearning komplett neu starten
LmsActRestartWarning: Das vorhandene ELearning wird komplett gelöscht! Für Inhaber einer gültigen Fahrlizenz werden später Benutzer und Passwort neu vergeben und es sollte eine neue Benachrichtigung versendet werden. Hinweis: Es kann mehrere Stunden dauern, bis das LMS diese Anfrage umgesetzt hat. LmsActRestartWarning: Das vorhandene ELearning wird komplett gelöscht! Für Inhaber einer gültigen Lizenz werden später Benutzer und Passwort neu vergeben und es sollte eine neue Benachrichtigung versendet werden. Hinweis: Es kann mehrere Stunden dauern, bis das LMS diese Anfrage umgesetzt hat.
LmsActRestartFeedback n@Int m@Int: #{n}/#{m} ELearning Nutzer wurden komplett neu gestartet mit neuem Login und Passwort. LmsActRestartFeedback n@Int m@Int: #{n}/#{m} ELearning Nutzer wurden komplett neu gestartet mit neuem Login und Passwort.
LmsActRestartExtend: Gültig bis ggf. erhöhen für die nächsten # Tage LmsActRestartExtend: Gültig bis ggf. erhöhen für die nächsten # Tage
LmsActRestartUnblock: Entzug ggf. aufheben LmsActRestartUnblock: Entzug ggf. aufheben

View File

@ -107,6 +107,8 @@ QualificationActUnblock: Clear revocation
QualificationActRenew: Renew qualification QualificationActRenew: Renew qualification
QualificationActGrant: Grant qualification QualificationActGrant: Grant qualification
QualificationActGrantWarning: Use with caution in rare exceptional cases only! Any revocation will be undone. QualificationActGrantWarning: Use with caution in rare exceptional cases only! Any revocation will be undone.
QualificationActStartELearning: Manually (re)start elearning for valid qualification holders
QualificationActStartELearningStatus l n m: Elearning #{l} (re)started for #{n}/#{m} users. Note: It may take a while, until the elearning is activated.
QualificationStatusBlock l n m: #{n}/#{m} #{l} revoked QualificationStatusBlock l n m: #{n}/#{m} #{l} revoked
QualificationStatusUnblock l n m: #{n}/#{m} #{l} reactivated QualificationStatusUnblock l n m: #{n}/#{m} #{l} reactivated
LmsInactive: Currently no active elearning LmsInactive: Currently no active elearning

View File

@ -14,7 +14,7 @@ module Handler.Qualification
import Import import Import
-- import Jobs import Jobs
import Handler.Utils import Handler.Utils
import Handler.Utils.Users import Handler.Utils.Users
import Handler.Utils.LMS import Handler.Utils.LMS
@ -274,6 +274,7 @@ data QualificationTableAction
| QualificationActUnblock | QualificationActUnblock
| QualificationActRenew | QualificationActRenew
| QualificationActGrant | QualificationActGrant
| QualificationActStartELearning
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic) deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic)
instance Universe QualificationTableAction instance Universe QualificationTableAction
@ -293,10 +294,11 @@ data QualificationTableActionData
= QualificationActExpireData = QualificationActExpireData
| QualificationActUnexpireData | QualificationActUnexpireData
| QualificationActBlockSupervisorData | QualificationActBlockSupervisorData
| QualificationActBlockData { qualTableActBlockReason :: Text, qualTableActNotify :: Bool, qualTableActRemoveSupervisors :: Bool } | QualificationActBlockData { qualTableActBlockReason :: Text, qualTableActNotify :: Bool, qualTableActRemoveSupervisors :: Bool }
| QualificationActUnblockData { qualTableActBlockReason :: Text, qualTableActNotify :: Bool} | QualificationActUnblockData { qualTableActBlockReason :: Text, qualTableActNotify :: Bool }
| QualificationActRenewData { qualTableActChangeReason :: Text} | QualificationActRenewData { qualTableActChangeReason :: Text }
| QualificationActGrantData { qualTableActGrantUntil :: Day } | QualificationActGrantData { qualTableActGrantUntil :: Day }
| QualificationActStartELearningData -- { qualTableActELearnUntil :: Maybe Day }
deriving (Eq, Ord, Show, Generic) deriving (Eq, Ord, Show, Generic)
isExpiryAct :: QualificationTableActionData -> Bool isExpiryAct :: QualificationTableActionData -> Bool
@ -390,7 +392,7 @@ mkQualificationTable isAdmin (Entity qid quali) acts cols psValidator = do
, single ("last-notified" , SortColumn $ queryQualUser >>> (E.^. QualificationUserLastNotified)) , single ("last-notified" , SortColumn $ queryQualUser >>> (E.^. QualificationUserLastNotified))
, single ("valid-until" , SortColumn $ queryQualUser >>> (E.^. QualificationUserValidUntil)) , single ("valid-until" , SortColumn $ queryQualUser >>> (E.^. QualificationUserValidUntil))
, single ("blocked" , SortColumnNeverNull $ queryQualBlock >>> (E.?. QualificationUserBlockFrom)) , single ("blocked" , SortColumnNeverNull $ queryQualBlock >>> (E.?. QualificationUserBlockFrom))
, single ("lms-status-plus",SortColumnNeverNull $ \row -> E.coalesce [ E.joinV (queryLmsUser row E.?. LmsUserStatusDay) , single ("lms-status-plus",SortColumnNullsInv $ \row -> E.coalesce [ E.joinV (queryLmsUser row E.?. LmsUserStatusDay)
, E.joinV (queryLmsUser row E.?. LmsUserNotified) , E.joinV (queryLmsUser row E.?. LmsUserNotified)
, queryLmsUser row E.?. LmsUserStarted]) , queryLmsUser row E.?. LmsUserStarted])
, single ("schedule-renew", SortColumnNullsInv $ queryQualUser >>> (E.^. QualificationUserScheduleRenewal)) , single ("schedule-renew", SortColumnNullsInv $ queryQualUser >>> (E.^. QualificationUserScheduleRenewal))
@ -571,6 +573,8 @@ postQualificationR sid qsh = do
, singletonMap QualificationActGrant $ QualificationActGrantData , singletonMap QualificationActGrant $ QualificationActGrantData
<$> apopt dayField (fslI MsgLmsQualificationValidUntil) dayExpiry <$> apopt dayField (fslI MsgLmsQualificationValidUntil) dayExpiry
<* aformMessage msgGrantWarning <* aformMessage msgGrantWarning
, singletonMap QualificationActStartELearning $ pure QualificationActStartELearningData
-- <$> aopt dayField (fslI MsgQualificationReduceValidUntil) Nothing
] isAdmin ] isAdmin
linkLmsUser = toMaybe isAdmin (LmsUserR sid qsh) linkLmsUser = toMaybe isAdmin (LmsUserR sid qsh)
linkUserName = bool ForProfileR ForProfileDataR isAdmin linkUserName = bool ForProfileR ForProfileDataR isAdmin
@ -613,6 +617,19 @@ postQualificationR sid qsh = do
runDB . forM_ selectedUsers $ upsertQualificationUser qid now grantValidday Nothing "Admin" runDB . forM_ selectedUsers $ upsertQualificationUser qid now grantValidday Nothing "Admin"
addMessageI (if 0 < Set.size selectedUsers then Success else Warning) . MsgTutorialUserGrantedQualification $ Set.size selectedUsers addMessageI (if 0 < Set.size selectedUsers then Success else Warning) . MsgTutorialUserGrantedQualification $ Set.size selectedUsers
reloadKeepGetParams $ QualificationR sid qsh reloadKeepGetParams $ QualificationR sid qsh
(QualificationActStartELearningData, Set.toList -> selectedUsers) | isAdmin -> do
-- whenIsJust mbExpDay $ \expDay ->
-- when expDay > nowaday $
-- -- updateWhere [QualificationUserQualification ==. qid, QualificationUserUser <-. selectedUsers, QualificationUserValidUntil >. expDay] [QualificationUserValidUntil =. expDay] -- DO NOT USE: no audit
-- NOTE: if needed, create function Handler.Utils.Qualification.updateQualificationUser qid QualificationChangeReason -> Day -> [UserId] -> DB Int
validQualHolderEnts <- runDB $ selectValidQualifications qid selectedUsers now
let validQualHolders = view (_entityVal . _qualificationUserUser) <$> validQualHolderEnts
jobs <- forM validQualHolders $ queueJob . JobLmsEnqueueUser qid
let nrTodo = length selectedUsers
nrEnqueued = length $ catMaybes jobs
addMessageI (bool Warning Success $ nrEnqueued > 0 && nrEnqueued == nrTodo) $ MsgQualificationActStartELearningStatus qsh nrEnqueued nrTodo
-- transaction audit identical to automatic start, performed by JobLmsEnqueueUser
reloadKeepGetParams $ QualificationR sid qsh
(action, selectedUsers) | isExpiryAct action -> do (action, selectedUsers) | isExpiryAct action -> do
let isUnexpire = action == QualificationActUnexpireData let isUnexpire = action == QualificationActUnexpireData
upd <- runDB $ do upd <- runDB $ do

View File

@ -166,7 +166,7 @@ upsertQualificationUser qualificationUserQualification startTime qualificationU
} }
-- | Renew an existing valid qualification, ignoring all blocks otherwise -- | Renew an existing valid qualification, ignoring all blocks otherwise
-- renewValidQualificationUsers :: QualificationId -> Maybe UTCTime -> [UserId] -> DB Int -- not general enough for use in YesodJobDB -- renewValidQualificationUsers :: QualificationId -> Maybe QualificationChangeReason -> Maybe UTCTime -> [UserId] -> DB Int -- not general enough for use in YesodJobDB
renewValidQualificationUsers :: renewValidQualificationUsers ::
( AuthId (HandlerSite m) ~ Key User ( AuthId (HandlerSite m) ~ Key User
, IsPersistBackend (YesodPersistBackend (HandlerSite m)) , IsPersistBackend (YesodPersistBackend (HandlerSite m))

View File

@ -129,7 +129,7 @@ dispatchJobLmsEnqueueUser qid uid = JobHandlerAtomic act
qprefix = fst <$> Text.uncons (Text.toLower qshort) qprefix = fst <$> Text.uncons (Text.toLower qshort)
identsInUseVs <- E.select $ do identsInUseVs <- E.select $ do
lui <- E.from $ lui <- E.from $
( (E.^. LmsUserIdent) <$> E.from (E.table @LmsUser ) ) -- no filter by Qid, since LmsIdents must be unique across all ( (E.^. LmsUserIdent) <$> E.from (E.table @LmsUser ) ) -- no filter by qid, since LmsIdents must be unique across all
`E.union_` `E.union_`
( (E.^. LmsReportIdent) <$> E.from (E.table @LmsReport ) ) -- V2 ( (E.^. LmsReportIdent) <$> E.from (E.table @LmsReport ) ) -- V2
E.orderBy [E.asc lui] E.orderBy [E.asc lui]

View File

@ -40,7 +40,7 @@ data LmsStatus = LmsExpired
| LmsSuccess | LmsSuccess
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, NFData, Universe, Finite) deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, NFData, Universe, Finite)
-- embedRenderMessage ''UniWorX ''LmsStatus (uncurry ((<>) . (<> "Status")) . Text.splitAt 3) -- moved to src/Foundation.hs -- embedRenderMessage ''UniWorX ''LmsStatus (uncurry ((<>) . (<> "Status")) . Text.splitAt 3) -- moved to src/Foundation.I18n
deriveJSON defaultOptions deriveJSON defaultOptions
{ constructorTagModifier = camelToPathPiece' 1 -- remove lms from constructor { constructorTagModifier = camelToPathPiece' 1 -- remove lms from constructor