fix(sap): combine immediate next day licence chnages for SAP

This commit is contained in:
Steffen Jost 2023-10-17 12:19:47 +02:00
parent b4a88abcf8
commit cbb44f106a
2 changed files with 52 additions and 24 deletions

View File

@ -76,24 +76,18 @@ sapRes2csv = concatMap procRes
-- | compute a series of valid periods, assume that lists is already sorted by Day
-- the lists encodes qualification_user_blocks with block=False/unblock=True
compileBlocks :: Day -> Day -> [(Day,Bool)] -> [(Day, Day)]
compileBlocks dfrom duntil [] = [(dfrom, duntil )]
compileBlocks dfrom duntil [(d,False)] = [(dfrom, min duntil d)] -- redundant, but common case
compileBlocks dfrom duntil (p1@(d1,u1):(d2,u2):bs)
| u1 == u2 = compileBlocks dfrom duntil (p1:bs) -- superfluous block/unblock
| u2, dfrom < d1, d1 < d2, d2 < duntil = (dfrom, d1) : compileBlocks d2 duntil bs -- block and reinstated later
compileBlocks dfrom duntil ((_,True ):bs) = compileBlocks dfrom duntil bs -- superfluous unblock
compileBlocks dfrom duntil ((_,False):bs) = compileBlocks dfrom duntil bs -- should only occur if blocks/unblock happened on same day
compileBlocks dStart dEnd = go (dStart, True)
where
go :: (Day,Bool) -> [(Day,Bool)] -> [(Day, Day)]
go (d,s) ((d1,s1):r1@((d2,s2):r2))
| d1 == d2 || succ d1 == d2 || s == s1 || d1 < d = go (d,s) r1 -- ignore unnecessary change
go (d,s) ((d1,s1):r1)
| s, d < d1, d1 < dEnd = (d,d1) : go (d1,s1) r1 -- valid interval found
| otherwise = go (d1,s1) r1 -- ignore invalid interval
go (d,s) []
| s = [(d,dEnd)]
| otherwise = []
-- Alternative Version constructed first, probably more efficient, but GHC does not recognize pattern matching as complete
-- compileBlocks :: Day -> Day -> [(Day,Bool)] -> [(Day, Day)]
-- compileBlocks dfrom duntil (p1@(d1,u1):p2@(d2,u2):bs)
-- | u1 == u2 = compileBlocks dfrom duntil (p1:bs)
-- | u2, d1 < duntil
-- , d2 < duntil = (dfrom,d1) : compileBlocks d2 duntil bs
-- compileBlocks dfrom duntil ((d1,True):bs) = compileBlocks dfrom duntil bs
-- compileBlocks dfrom duntil [(d1,False)] = [(dfrom, min duntil d1)]
-- compileBlocks dfrom duntil _ = [(dfrom,duntil)]
-- | Deliver all employess with a successful LDAP synch within the last 3 months
getQualificationSAPDirectR :: Handler TypedContent

View File

@ -10,7 +10,7 @@ import TestImport
import Handler.SAP
{-
data BlockIntervalTest = BlockIntervalTest Day Day [(Day,Bool)]
deriving (Show, Eq, Ord)
@ -26,7 +26,7 @@ instance Arbitrary BlockIntervalTest where
let ds = ncons h (fst <$> t')
dmin = minimum ds
dmax = maximum ds
dFrom <- arbitrary `suchThat` (< dmin)
dFrom <- arbitrary `suchThat` (<= dmin)
dUntil <- arbitrary `suchThat` (>= dmax)
return $ BlockIntervalTest dFrom dUntil $ sort blocks
@ -34,13 +34,30 @@ instance Arbitrary BlockIntervalTest where
= [BlockIntervalTest dF dU [] | dF <- shrink dFrom, dU <- shrink dUntil, dF < dU]
shrink (BlockIntervalTest dFrom dUntil blocks)
= [BlockIntervalTest dFrom dUntil b | b <- shrink blocks, all ((dFrom <=) . fst) b]
-}
{- These alternative implementations do NOT meet the specifications and thus cannot be used for testing
compileBlocks :: Day -> Day -> [(Day,Bool)] -> [(Day, Day)]
compileBlocks dfrom duntil [] = [(dfrom, duntil)]
compileBlocks dfrom duntil [(d,False)]
| dend <- min duntil d, dfrom < dend = [(dfrom, dend)] -- redundant, but common case
| otherwise = []
compileBlocks dfrom duntil (p1@(d1,u1):p2@(d2,u2):bs)
| u1 == u2 = compileBlocks dfrom duntil (p1:bs) -- superfluous block/unblock
| d1 == d2 = compileBlocks dfrom duntil (p2:bs) -- eliminate same day changes
| u2, dfrom < d1, d1 < d2, d2 < duntil = (dfrom, d1) : compileBlocks d2 duntil bs -- block and reinstated later
compileBlocks dfrom duntil ((_,True ):bs) = compileBlocks dfrom duntil bs -- superfluous unblock
compileBlocks dfrom duntil ((d,False):bs)
| dfrom >= d = compileBlocks dfrom duntil bs -- should only occur if blocks/unblock happened on same day
cmpBlocks :: BlockIntervalTest -> [(Day,Day)]
cmpBlocks (BlockIntervalTest dFrom dUntil blocks) = makePeriods dFrom dUntil $ cleanBlocks $ sort blocks
where
cleanBlocks ((_,True):r) = cleanBlocks r
cleanBlocks (b1@(_,False):b2@(_,True):r) = b1:b2:cleanBlocks r
cleanBlocks (b1@(d1,False):b2@(d2,True):r)
| d1 < d1 = b1:b2:cleanBlocks r
| otherwise = cleanBlocks r
cleanBlocks (b1@(_,False): (_,False):r) = cleanBlocks (b1:r)
cleanBlocks r@[(_,False)] = r
cleanBlocks [] = []
@ -50,12 +67,29 @@ cmpBlocks (BlockIntervalTest dFrom dUntil blocks) = makePeriods dFrom dUntil $ c
| otherwise = [(a,d1)]
makePeriods a b [(d,False)] = [(a,min b d)]
makePeriods a b _ = [(a,b)]
-}
spec :: Spec
spec = do
describe "SAP.compileBlocks" $ do
it "yields basic intervals" . property $
\bit@(BlockIntervalTest dFrom dUntil blocks) ->
cmpBlocks bit == compileBlocks dFrom dUntil blocks
it "works on examples" . example $ do
let wA = fromGregorian 2002 1 11
wE = fromGregorian 2025 4 30
w0 = fromGregorian 2001 9 22
w1 = fromGregorian 2023 9 22
w2 = fromGregorian 2023 10 16
w3 = fromGregorian 2023 11 17
compileBlocks wA wE [] `shouldBe` [(wA,wE)]
compileBlocks wA wE [(w1,False)] `shouldBe` [(wA,w1)]
compileBlocks wA wE [(w1,False),(w2,True)] `shouldBe` [(wA,w1),(w2,wE)]
compileBlocks wA wE [(wA,False),(w1,True)] `shouldBe` [(w1,wE)]
compileBlocks wA wE [(wA,True),(wA,False),(w1,True)] `shouldBe` [(w1,wE)]
compileBlocks wA wE [(wA,False),(wA,True),(w1,True)] `shouldBe` [(wA,wE)]
compileBlocks wA wE [(wA,False),(w1,True),(w2,False)] `shouldBe` [(w1,w2)]
compileBlocks wA wE [(w1,False),(w1,True),(w1,False),(w1,True),(w1,False),(w2,True)] `shouldBe` [(wA,w1),(w2,wE)]
compileBlocks wA wE [(w1,False),(succ w1,True),(succ w1,False),(w2,True)] `shouldBe` [(wA,succ w1),(w2,wE)]
compileBlocks wA wE [(w0,True),(w1,True),(w1,False),(w1,True),(w1,False),(w2,True),(w3,True)] `shouldBe` [(wA,w1),(w2,wE)]
-- it "yields basic intervals" . property $
-- \bit@(BlockIntervalTest dFrom dUntil blocks) ->
-- cmpBlocks bit == compileBlocks dFrom dUntil blocks