test(avs): add more encodings and test cases vor avs datatypes
This commit is contained in:
parent
afa1ceff20
commit
d125bcdc9c
@ -2,6 +2,8 @@
|
|||||||
--
|
--
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
|
||||||
module Handler.Utils.Avs
|
module Handler.Utils.Avs
|
||||||
( upsertAvsUser, upsertAvsUserById, upsertAvsUserByCard
|
( upsertAvsUser, upsertAvsUserById, upsertAvsUserByCard
|
||||||
, getLicence, getLicenceDB
|
, getLicence, getLicenceDB
|
||||||
@ -27,6 +29,10 @@ import Foundation.Yesod.Auth (upsertCampusUserByCn,CampusUserConversionException
|
|||||||
import Handler.Utils.Company
|
import Handler.Utils.Company
|
||||||
import Handler.Users.Add
|
import Handler.Users.Add
|
||||||
|
|
||||||
|
--import qualified Database.Esqueleto.Experimental as E -- needs TypeApplications Lang-Pragma
|
||||||
|
--import qualified Database.Esqueleto.Utils as E
|
||||||
|
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
-- AVS Exceptions --
|
-- AVS Exceptions --
|
||||||
--------------------
|
--------------------
|
||||||
@ -84,7 +90,7 @@ setLicence uid lic = do
|
|||||||
|
|
||||||
setLicenceAvs :: AvsPersonId -> AvsLicence -> DB ()
|
setLicenceAvs :: AvsPersonId -> AvsLicence -> DB ()
|
||||||
setLicenceAvs apid lic = do
|
setLicenceAvs apid lic = do
|
||||||
let req = Set.singleton $ AvsPersonLicence apid lic
|
let req = Set.singleton $ AvsPersonLicence { avsLicenceRampLicence = lic, avsLicencePersonID = apid }
|
||||||
setLicencesAvs req
|
setLicencesAvs req
|
||||||
|
|
||||||
-- setLicencesAvs :: Set AvsPersonLicence -> DB ()
|
-- setLicencesAvs :: Set AvsPersonLicence -> DB ()
|
||||||
@ -95,7 +101,8 @@ setLicencesAvs pls = do
|
|||||||
response <- throwLeftM . avsQuerySetLicences $ AvsQuerySetLicences pls
|
response <- throwLeftM . avsQuerySetLicences $ AvsQuerySetLicences pls
|
||||||
case response of
|
case response of
|
||||||
AvsResponseSetLicencesError{..} -> do
|
AvsResponseSetLicencesError{..} -> do
|
||||||
$logErrorS "AVS" $ "Set licence failed completely: " <> avsResponseSetLicencesStatus <> ". Details: " <> avsResponseSetLicencesMessage
|
let msg = "Set licence failed completely: " <> avsResponseSetLicencesStatus <> ". Details: " <> avsResponseSetLicencesMessage
|
||||||
|
$logErrorS "AVS" msg
|
||||||
throwM $ AvsSetLicencesFailed avsResponseSetLicencesStatus
|
throwM $ AvsSetLicencesFailed avsResponseSetLicencesStatus
|
||||||
AvsResponseSetLicences responses ->
|
AvsResponseSetLicences responses ->
|
||||||
forM_ responses $ \AvsLicenceResponse{..} ->
|
forM_ responses $ \AvsLicenceResponse{..} ->
|
||||||
@ -109,8 +116,23 @@ setLicencesAvs pls = do
|
|||||||
-- TODO: turn into a job, once the interface is actually available
|
-- TODO: turn into a job, once the interface is actually available
|
||||||
checkLicences :: Handler ()
|
checkLicences :: Handler ()
|
||||||
checkLicences = do
|
checkLicences = do
|
||||||
AvsQuery{..} <- maybeThrowM AvsInterfaceUnavailable $ getsYesod $ view _appAvsQuery
|
{-
|
||||||
AvsResponseGetLicences _licences <- throwLeftM avsQueryGetAllLicences
|
AvsQuery{..} <- maybeThrowM AvsInterfaceUnavailable $ getsYesod $ view _appAvsQuery
|
||||||
|
AvsResponseGetLicences licences <- throwLeftM avsQueryGetAllLicences
|
||||||
|
|
||||||
|
--let (vorfeld, nonvorfeld) = Set.partition (`avsPersonLicenceIs` AvsLicenceVorfeld) licences
|
||||||
|
-- rollfeld = Set.filter (`avsPersonLicenceIs` AvsLicenceRollfeld) nonvorfeld
|
||||||
|
let (noOrVorfeld, rollfeld) = Set.spanAntitone (`avsPersonLicenceIsLEQ` AvsLicenceVorfeld) licences
|
||||||
|
(_nolicence , vorfeld) = Set.spanAntitone (`avsPersonLicenceIsLEQ` AvsNoLicence) noOrVorfeld
|
||||||
|
now <- liftIO getCurrentTime
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
runDB $ do
|
||||||
|
E.select $ do
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
--TODO this must be chunked into separate jobs/tasks
|
--TODO this must be chunked into separate jobs/tasks
|
||||||
--forM licences $ \AvsPersonLicence{..} -> do
|
--forM licences $ \AvsPersonLicence{..} -> do
|
||||||
error "CONTINUE HERE" -- TODO STUB
|
error "CONTINUE HERE" -- TODO STUB
|
||||||
|
|||||||
@ -164,8 +164,9 @@ discernAvsIds someid = aux someid
|
|||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
aux _ = Right . AvsPersonId <$> readMay someid -- must always succeed at that point
|
aux _ = Right . AvsPersonId <$> readMay someid -- must always succeed at that point
|
||||||
|
|
||||||
|
|
||||||
data AvsLicence = AvsNoLicence | AvsLicenceVorfeld | AvsLicenceRollfeld
|
data AvsLicence = AvsNoLicence | AvsLicenceVorfeld | AvsLicenceRollfeld
|
||||||
deriving (Bounded, Enum, Eq, Ord, Read, Show, Generic, Typeable)
|
deriving (Bounded, Enum, Eq, Ord, Read, Show, Generic, Typeable, Finite, Universe)
|
||||||
|
|
||||||
instance ToJSON AvsLicence where
|
instance ToJSON AvsLicence where
|
||||||
-- toJSON al = Number $ fromEnum AvsLicence -- would do, but...
|
-- toJSON al = Number $ fromEnum AvsLicence -- would do, but...
|
||||||
@ -176,13 +177,26 @@ instance ToJSON AvsLicence where
|
|||||||
instance FromJSON AvsLicence where
|
instance FromJSON AvsLicence where
|
||||||
parseJSON (Number n) | n == 1 = pure AvsLicenceVorfeld -- ordered by occurrence, n==1 is most common case
|
parseJSON (Number n) | n == 1 = pure AvsLicenceVorfeld -- ordered by occurrence, n==1 is most common case
|
||||||
| n == 2 = pure AvsLicenceRollfeld
|
| n == 2 = pure AvsLicenceRollfeld
|
||||||
| n == 0 = pure AvsNoLicence -- n==0 never received from AVS, only sent to AVS
|
| n == 0 = pure AvsNoLicence -- n==0 never received from AVS, only sent to AVS
|
||||||
#ifdef DEVELOPMENT
|
#ifdef DEVELOPMENT
|
||||||
parseJSON invalid = prependFailure "parsing AvsLicence failed, " $ fail $ "expected Int value being 0, 1 or 2. Found " ++ show invalid
|
parseJSON invalid = prependFailure "parsing AvsLicence failed, " $ fail $ "expected Int value being 0, 1 or 2. Found " ++ show invalid
|
||||||
#else
|
#else
|
||||||
parseJSON _ = pure AvsNoLicence -- we simply ignore all other values
|
parseJSON _ = pure AvsNoLicence -- we simply ignore all other values
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
-- we assume that the Ord-Instance is respected by the SQL Backend!
|
||||||
|
instance PersistField AvsLicence where
|
||||||
|
toPersistValue = PersistInt64 . fromIntegral . fromEnum
|
||||||
|
fromPersistValue (PersistInt64 v')
|
||||||
|
| let v = fromIntegral v'
|
||||||
|
, v >= fromEnum (minBound::AvsLicence)
|
||||||
|
, v <= fromEnum (maxBound::AvsLicence)
|
||||||
|
= Right $ toEnum v
|
||||||
|
fromPersistValue other = Left $ "Encoding of AvsLicence " <> tshow other <> " is out of range"
|
||||||
|
|
||||||
|
instance PersistFieldSql AvsLicence where
|
||||||
|
sqlType _ = SqlInt64
|
||||||
|
|
||||||
-- | Ought to be identical to QualificationShortname!
|
-- | Ought to be identical to QualificationShortname!
|
||||||
licence2char :: AvsLicence -> Char
|
licence2char :: AvsLicence -> Char
|
||||||
licence2char AvsNoLicence = '0'
|
licence2char AvsNoLicence = '0'
|
||||||
@ -352,8 +366,8 @@ deriveJSON defaultOptions
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
data AvsPersonLicence = AvsPersonLicence
|
data AvsPersonLicence = AvsPersonLicence
|
||||||
{ avsLicencePersonID :: AvsPersonId
|
{ avsLicenceRampLicence :: AvsLicence
|
||||||
, avsLicenceRampLicence :: AvsLicence
|
, avsLicencePersonID :: AvsPersonId
|
||||||
}
|
}
|
||||||
deriving (Eq, Ord, Show, Generic, Typeable)
|
deriving (Eq, Ord, Show, Generic, Typeable)
|
||||||
deriveJSON defaultOptions
|
deriveJSON defaultOptions
|
||||||
@ -363,6 +377,13 @@ deriveJSON defaultOptions
|
|||||||
, rejectUnknownFields = False
|
, rejectUnknownFields = False
|
||||||
} ''AvsPersonLicence
|
} ''AvsPersonLicence
|
||||||
|
|
||||||
|
avsPersonLicenceIs :: AvsPersonLicence -> AvsLicence -> Bool
|
||||||
|
avsPersonLicenceIs = (==) . avsLicenceRampLicence
|
||||||
|
|
||||||
|
avsPersonLicenceIsLEQ :: AvsPersonLicence -> AvsLicence -> Bool
|
||||||
|
avsPersonLicenceIsLEQ = (<=) . avsLicenceRampLicence
|
||||||
|
|
||||||
|
|
||||||
data AvsLicenceResponse = AvsLicenceResponse
|
data AvsLicenceResponse = AvsLicenceResponse
|
||||||
{ avsResponsePersonID :: AvsPersonId
|
{ avsResponsePersonID :: AvsPersonId
|
||||||
, avsResponseSuccess :: SloppyBool
|
, avsResponseSuccess :: SloppyBool
|
||||||
|
|||||||
@ -623,10 +623,7 @@ mTuple = liftA2 (,)
|
|||||||
-- Lists --
|
-- Lists --
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
-- avoids some parenthesis within guards
|
-- avoids some parenthesis within guards
|
||||||
>>>>>>> master
|
|
||||||
notNull :: MonoFoldable mono => mono -> Bool
|
notNull :: MonoFoldable mono => mono -> Bool
|
||||||
notNull = not . null
|
notNull = not . null
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,9 @@ module Utils.TypesSpec where
|
|||||||
import TestImport
|
import TestImport
|
||||||
import Utils
|
import Utils
|
||||||
|
|
||||||
|
import qualified Data.Aeson as Aeson
|
||||||
|
|
||||||
|
|
||||||
instance Arbitrary SloppyBool where
|
instance Arbitrary SloppyBool where
|
||||||
arbitrary = SloppyBool <$> arbitrary
|
arbitrary = SloppyBool <$> arbitrary
|
||||||
shrink (SloppyBool x) = SloppyBool <$> shrink x
|
shrink (SloppyBool x) = SloppyBool <$> shrink x
|
||||||
@ -95,6 +98,8 @@ spec = do
|
|||||||
[ eqLaws, ordLaws, showLaws, jsonLaws ]
|
[ eqLaws, ordLaws, showLaws, jsonLaws ]
|
||||||
lawsCheckHspec (Proxy @AvsDataPerson) --iso failed
|
lawsCheckHspec (Proxy @AvsDataPerson) --iso failed
|
||||||
[ eqLaws, ordLaws, showLaws, jsonLaws ]
|
[ eqLaws, ordLaws, showLaws, jsonLaws ]
|
||||||
|
lawsCheckHspec (Proxy @AvsLicence)
|
||||||
|
[ eqLaws, ordLaws, showLaws, jsonLaws, persistFieldLaws ]
|
||||||
lawsCheckHspec (Proxy @AvsPersonLicence)
|
lawsCheckHspec (Proxy @AvsPersonLicence)
|
||||||
[ eqLaws, ordLaws, showLaws, jsonLaws ]
|
[ eqLaws, ordLaws, showLaws, jsonLaws ]
|
||||||
lawsCheckHspec (Proxy @AvsLicenceResponse)
|
lawsCheckHspec (Proxy @AvsLicenceResponse)
|
||||||
@ -116,6 +121,24 @@ spec = do
|
|||||||
lawsCheckHspec (Proxy @AvsQuerySetLicences)
|
lawsCheckHspec (Proxy @AvsQuerySetLicences)
|
||||||
[ eqLaws, showLaws, jsonLaws]
|
[ eqLaws, showLaws, jsonLaws]
|
||||||
|
|
||||||
|
describe "AvsLicence" $ do
|
||||||
|
it "ordering is consistent with its PersistField instance" . property $ -- this assumption is used in Handler.Utils.Avs.checkLicences
|
||||||
|
\a (b :: AvsLicence) -> compare a b == compare (toPersistValue a) (toPersistValue b)
|
||||||
|
it "assigns AvsLicence fixed SQL values" . example $ do -- ensure that DB encoding does not change unnoticed
|
||||||
|
toPersistValue AvsLicenceVorfeld `shouldBe` toPersistValue (1::Int64)
|
||||||
|
toPersistValue AvsLicenceRollfeld `shouldBe` toPersistValue (2::Int64)
|
||||||
|
it "assigns AvsLicence fixed JSON values" . example $ do -- ensure that SQL encoding does not change unnoticed
|
||||||
|
Aeson.toJSON AvsLicenceVorfeld `shouldBe` Aeson.Number 1
|
||||||
|
Aeson.toJSON AvsLicenceRollfeld `shouldBe` Aeson.Number 2
|
||||||
|
|
||||||
|
describe "Ord AvsPersonLicence" $ do
|
||||||
|
it "proritises avsLicenceRampLicence" . property $
|
||||||
|
\p0 p1@AvsPersonLicence{avsLicenceRampLicence=v1} ->
|
||||||
|
let p2@AvsPersonLicence{avsLicenceRampLicence=v2} = p0 in
|
||||||
|
(v1 /= v2) ==> compare p1 p2 == compare v1 v2
|
||||||
|
it "has antitone Function avsPersonLicenceIsGEQ" . property $ -- this assumption is used in Handler.Utils.Avs.checkLicences
|
||||||
|
\j k l -> j < k ==> avsPersonLicenceIsLEQ j l >= avsPersonLicenceIsLEQ k l
|
||||||
|
|
||||||
describe "Ord AvsDataCard" $ do
|
describe "Ord AvsDataCard" $ do
|
||||||
it "prioritises avsDataValid" . property $
|
it "prioritises avsDataValid" . property $
|
||||||
\p0 p1@AvsDataPersonCard{avsDataValid=v1} ->
|
\p0 p1@AvsDataPersonCard{avsDataValid=v1} ->
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user