refactor(qualification): WIP db migration implemented
This commit is contained in:
parent
00d406dd13
commit
d377d717d2
@ -60,7 +60,7 @@ QualificationUser
|
|||||||
validUntil Day -- addGregorianMonthsRollOver (toInteger renewalMonths) qualificationUserValidUntil
|
validUntil Day -- addGregorianMonthsRollOver (toInteger renewalMonths) qualificationUserValidUntil
|
||||||
lastRefresh Day -- lastRefresh > validUntil possible, if Qualification^elearningOnly == False
|
lastRefresh Day -- lastRefresh > validUntil possible, if Qualification^elearningOnly == False
|
||||||
firstHeld Day -- first time the qualification was earned, should never change
|
firstHeld Day -- first time the qualification was earned, should never change
|
||||||
blockedDue QualificationBlocked Maybe -- isJust means that the qualification is currently revoked
|
-- blockedDue QualificationBlocked Maybe -- TODO: refactor own table isJust means that the qualification is currently revoked
|
||||||
scheduleRenewal Bool default=true -- if false, no automatic renewal is scheduled and the qualification expires
|
scheduleRenewal Bool default=true -- if false, no automatic renewal is scheduled and the qualification expires
|
||||||
lastNotified UTCTime default=now() -- last notficiation about being invalid
|
lastNotified UTCTime default=now() -- last notficiation about being invalid
|
||||||
-- temporärer Entzug vorsehen -- SAP Schnittstelle muss dann angepasst werden
|
-- temporärer Entzug vorsehen -- SAP Schnittstelle muss dann angepasst werden
|
||||||
@ -68,6 +68,13 @@ QualificationUser
|
|||||||
UniqueQualificationUser qualification user
|
UniqueQualificationUser qualification user
|
||||||
deriving Generic
|
deriving Generic
|
||||||
|
|
||||||
|
QualificationUserBlock
|
||||||
|
qualificationUser QualificationUserId OnDeleteCascade OnUpdateCascade
|
||||||
|
from Day
|
||||||
|
until Day Maybe -- if Nothing then the block holds indefinitely
|
||||||
|
reason Text
|
||||||
|
deriving Eq Ord Read Show Generic
|
||||||
|
|
||||||
-- LMS Interface Tables, need regular processing by background jobs, per QualificationId:
|
-- LMS Interface Tables, need regular processing by background jobs, per QualificationId:
|
||||||
--
|
--
|
||||||
-- 1. Daily Job: Add to LmsUser daily all qualification holders with
|
-- 1. Daily Job: Add to LmsUser daily all qualification holders with
|
||||||
@ -119,6 +126,13 @@ LmsUser
|
|||||||
UniqueLmsQualificationUser qualification user -- each user may be enrolled at most once per course
|
UniqueLmsQualificationUser qualification user -- each user may be enrolled at most once per course
|
||||||
deriving Generic
|
deriving Generic
|
||||||
|
|
||||||
|
-- LmsUserStatus
|
||||||
|
-- lmsUser LmsUserId OnDeleteCascade OnUpdateCascade
|
||||||
|
-- result LmsStatus -- data LmsStatus = LmsBlocked | LmsExpired | LmsSuccess
|
||||||
|
-- day Day
|
||||||
|
-- UniqueLmsUserStatus lmsUser
|
||||||
|
-- deriving Generic
|
||||||
|
|
||||||
-- LmsUserlist stores LMS upload for later processing only
|
-- LmsUserlist stores LMS upload for later processing only
|
||||||
LmsUserlist
|
LmsUserlist
|
||||||
qualification QualificationId OnDeleteCascade OnUpdateCascade
|
qualification QualificationId OnDeleteCascade OnUpdateCascade
|
||||||
|
|||||||
@ -211,9 +211,9 @@ data Transaction
|
|||||||
}
|
}
|
||||||
| TransactionQualificationUserBlocking
|
| TransactionQualificationUserBlocking
|
||||||
{ transactionUser :: UserId -- qualification holder that is updated
|
{ transactionUser :: UserId -- qualification holder that is updated
|
||||||
-- , transactionQualificationUser :: QualificationUserId -- not neccessary due to UniqueQualificationUser
|
-- , transactionQualificationUser :: QualificationUserId -- not neccessary due to UniqueQualificationUser
|
||||||
, transactionQualification :: QualificationId
|
, transactionQualification :: QualificationId
|
||||||
, transactionQualificationBlock :: Maybe QualificationBlocked -- Nothing indicates unblocking
|
, transactionQualificationBlock :: QualificationUserBlock
|
||||||
}
|
}
|
||||||
deriving (Eq, Ord, Read, Show, Generic)
|
deriving (Eq, Ord, Read, Show, Generic)
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,12 @@ import qualified Database.Esqueleto.Utils as E
|
|||||||
import Handler.Utils.DateTime (toMidnight)
|
import Handler.Utils.DateTime (toMidnight)
|
||||||
|
|
||||||
|
|
||||||
|
mkQualificationBlocked :: QualificationBlockStandardReason -> Day -> Maybe Day -> QualificationUserBlock
|
||||||
|
mkQualificationBlocked reason qualificationUserBlockFrom qualificationUserBlockUntil = QualificationUserBlock{..}
|
||||||
|
where
|
||||||
|
qualificationUserBlockReason = qualificationBlockedReasonText reason
|
||||||
|
|
||||||
|
|
||||||
isValidQualification :: HasQualificationUser a => Day -> a -> Bool
|
isValidQualification :: HasQualificationUser a => Day -> a -> Bool
|
||||||
isValidQualification d q = d `inBetween` (q ^. hasQualificationUser . _qualificationUserFirstHeld
|
isValidQualification d q = d `inBetween` (q ^. hasQualificationUser . _qualificationUserFirstHeld
|
||||||
,q ^. hasQualificationUser . _qualificationUserValidUntil)
|
,q ^. hasQualificationUser . _qualificationUserValidUntil)
|
||||||
|
|||||||
@ -243,3 +243,9 @@ instance IsFileReference MaterialFile where
|
|||||||
fileReferenceTitleField = MaterialFileTitle
|
fileReferenceTitleField = MaterialFileTitle
|
||||||
fileReferenceContentField = MaterialFileContent
|
fileReferenceContentField = MaterialFileContent
|
||||||
fileReferenceModifiedField = MaterialFileModified
|
fileReferenceModifiedField = MaterialFileModified
|
||||||
|
|
||||||
|
deriveJSON defaultOptions
|
||||||
|
{ tagSingleConstructors = False
|
||||||
|
, fieldLabelModifier = camelToPathPiece' 2
|
||||||
|
, omitNothingFields = True
|
||||||
|
} ''QualificationUserBlock
|
||||||
|
|||||||
@ -92,6 +92,7 @@ data ManualMigration
|
|||||||
| Migration20210208StudyFeaturesRelevanceCachedUUIDs
|
| Migration20210208StudyFeaturesRelevanceCachedUUIDs
|
||||||
| Migration20210318CrontabSubmissionRatedNotification
|
| Migration20210318CrontabSubmissionRatedNotification
|
||||||
| Migration20210608SeparateTermActive
|
| Migration20210608SeparateTermActive
|
||||||
|
| Migration20230524QualificationUserBlock
|
||||||
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic)
|
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic)
|
||||||
deriving anyclass (Universe, Finite)
|
deriving anyclass (Universe, Finite)
|
||||||
|
|
||||||
@ -854,6 +855,23 @@ customMigrations = mapF $ \case
|
|||||||
ALTER TABLE "term" DROP COLUMN "active";
|
ALTER TABLE "term" DROP COLUMN "active";
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
Migration20230524QualificationUserBlock ->
|
||||||
|
unlessM (tableExists "qualification_user_block") $ do
|
||||||
|
[executeQQ|
|
||||||
|
CREATE TABLE "qualification_user_block" ("id" SERIAL8 PRIMARY KEY UNIQUE, "qualification_user" bigint NOT NULL, "from" date NOT NULL, "until" date, "reason" character varying NOT NULL)
|
||||||
|
CONSTRAINT qualification_user_fkey FOREIGN KEY (qualification_user) REFERENCES qualification_user(id)
|
||||||
|
|]
|
||||||
|
|
||||||
|
let getBlocks = [queryQQ|SELECT "id", "blocked_due" FROM "qualification_user" WHERE "blocked_due" IS NOT NULL|]
|
||||||
|
migrateBlocks [ fromPersistValue -> Right (quid :: QualificationUserId), fromPersistValue -> Right (Just (Legacy.QualificationBlocked{..} :: Legacy.QualificationBlocked)) ] =
|
||||||
|
[executeQQ|INSERT INTO "qualification_user_block" ("qualification_user", "from", "reason") VALUES (#{quid}, #{qualificationBlockedDay}, #{qualificationBlockedReason})|]
|
||||||
|
migrateBlocks _ = return ()
|
||||||
|
in runConduit $ getBlocks .| C.mapM_ migrateBlocks
|
||||||
|
|
||||||
|
[executeQQ|
|
||||||
|
ALTER TABLE "qualification_user" DROP COLUMN "blocked_due";
|
||||||
|
|]
|
||||||
|
|
||||||
|
|
||||||
tableExists :: MonadIO m => Text -> ReaderT SqlBackend m Bool
|
tableExists :: MonadIO m => Text -> ReaderT SqlBackend m Bool
|
||||||
tableExists table = do
|
tableExists table = do
|
||||||
|
|||||||
@ -124,3 +124,18 @@ examModeDNF :: ExamModeDNF -> Current.ExamModeDNF
|
|||||||
examModeDNF (ExamModeDNF PredDNF{..}) = Current.ExamModeDNF . Current.PredDNF $ Set.map (impureNonNull . Set.map toCurrentPredLiteral . toNullable) dnfTerms
|
examModeDNF (ExamModeDNF PredDNF{..}) = Current.ExamModeDNF . Current.PredDNF $ Set.map (impureNonNull . Set.map toCurrentPredLiteral . toNullable) dnfTerms
|
||||||
where toCurrentPredLiteral PLVariable{..} = Current.PLVariable plVar
|
where toCurrentPredLiteral PLVariable{..} = Current.PLVariable plVar
|
||||||
toCurrentPredLiteral PLNegated{..} = Current.PLNegated plVar
|
toCurrentPredLiteral PLNegated{..} = Current.PLNegated plVar
|
||||||
|
|
||||||
|
|
||||||
|
data QualificationBlocked = QualificationBlocked { qualificationBlockedDay :: Day
|
||||||
|
, qualificationBlockedReason :: Text
|
||||||
|
}
|
||||||
|
deriving (Eq, Ord, Read, Show, Generic, NFData)
|
||||||
|
|
||||||
|
-- makeLenses_ ''QualificationBlocked
|
||||||
|
--
|
||||||
|
deriveJSON defaultOptions
|
||||||
|
{ tagSingleConstructors = False
|
||||||
|
, fieldLabelModifier = camelToPathPiece' 2
|
||||||
|
, omitNothingFields = True
|
||||||
|
} ''QualificationBlocked
|
||||||
|
Current.derivePersistFieldJSON ''QualificationBlocked
|
||||||
@ -86,26 +86,6 @@ instance Csv.ToField LmsStatus where
|
|||||||
toField (LmsExpired d) = "Expired: " <> Csv.toField d
|
toField (LmsExpired d) = "Expired: " <> Csv.toField d
|
||||||
toField (LmsSuccess d) = "Success: " <> Csv.toField d
|
toField (LmsSuccess d) = "Success: " <> Csv.toField d
|
||||||
|
|
||||||
data QualificationBlocked = QualificationBlocked { qualificationBlockedDay :: Day
|
|
||||||
, qualificationBlockedReason :: Text
|
|
||||||
}
|
|
||||||
deriving (Eq, Ord, Read, Show, Generic, NFData)
|
|
||||||
|
|
||||||
makeLenses_ ''QualificationBlocked
|
|
||||||
|
|
||||||
deriveJSON defaultOptions
|
|
||||||
{ tagSingleConstructors = False
|
|
||||||
, fieldLabelModifier = camelToPathPiece' 2
|
|
||||||
, omitNothingFields = True
|
|
||||||
} ''QualificationBlocked
|
|
||||||
derivePersistFieldJSON ''QualificationBlocked
|
|
||||||
|
|
||||||
instance Csv.ToField QualificationBlocked where
|
|
||||||
toField QualificationBlocked{..} = "Blocked " <> Csv.toField qualificationBlockedDay <> " due to " <> Csv.toField qualificationBlockedReason
|
|
||||||
|
|
||||||
-- | ToMessage instance ignores contained timestamp by design
|
|
||||||
-- instance ToMessage QualificationBlocked where -- no longer used
|
|
||||||
-- toMessage QualificationBlocked{..} = qualificationBlockedReason
|
|
||||||
|
|
||||||
data QualificationBlockStandardReason
|
data QualificationBlockStandardReason
|
||||||
= QualificationBlockFailedELearning
|
= QualificationBlockFailedELearning
|
||||||
@ -121,11 +101,6 @@ qualificationBlockedReasonText =
|
|||||||
let dictionary :: Map.Map QualificationBlockStandardReason Text = Map.fromList [(r, tshow r) | r <- universeF]
|
let dictionary :: Map.Map QualificationBlockStandardReason Text = Map.fromList [(r, tshow r) | r <- universeF]
|
||||||
in (dictionary !) -- cannot fail due to universeF
|
in (dictionary !) -- cannot fail due to universeF
|
||||||
|
|
||||||
mkQualificationBlocked :: QualificationBlockStandardReason -> Day -> QualificationBlocked
|
|
||||||
mkQualificationBlocked reason qualificationBlockedDay = QualificationBlocked{..}
|
|
||||||
where
|
|
||||||
qualificationBlockedReason = qualificationBlockedReasonText reason
|
|
||||||
|
|
||||||
-- | LMS interface requires Bool to be encoded by 0 or 1 only
|
-- | LMS interface requires Bool to be encoded by 0 or 1 only
|
||||||
newtype LmsBool = LmsBool { lms2bool :: Bool }
|
newtype LmsBool = LmsBool { lms2bool :: Bool }
|
||||||
deriving (Eq, Ord, Read, Show, Generic)
|
deriving (Eq, Ord, Read, Show, Generic)
|
||||||
|
|||||||
@ -122,7 +122,9 @@ makeClassyFor_ ''StudySubTerms
|
|||||||
|
|
||||||
makeClassyFor_ ''Qualification
|
makeClassyFor_ ''Qualification
|
||||||
makeClassyFor_ ''QualificationUser
|
makeClassyFor_ ''QualificationUser
|
||||||
|
makeClassyFor_ ''QualificationUserBlock
|
||||||
makeClassyFor_ ''LmsUser
|
makeClassyFor_ ''LmsUser
|
||||||
|
-- makeClassyFor_ ''LmsUserStatus
|
||||||
makeClassyFor_ ''LmsUserlist
|
makeClassyFor_ ''LmsUserlist
|
||||||
makeClassyFor_ ''LmsResult
|
makeClassyFor_ ''LmsResult
|
||||||
makeClassyFor_ ''UserAvs
|
makeClassyFor_ ''UserAvs
|
||||||
|
|||||||
Reference in New Issue
Block a user