cqrs-example-0.6.0: src/Aggregates.hs
module Aggregates
( Project(..)
, ProjectId
, Task(..)
, TaskId
, User(..)
, UserId
, WorkUnit(..)
) where
import Control.Monad (liftM)
import Data.CQRS (Aggregate(..), GUID)
import Data.Default (Default(..))
import Data.Map (Map)
import Data.Serialize (Serialize(..), decode, encode)
import Data.Text (Text)
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Time.Calendar(Day(..), toGregorian, fromGregorian)
import Data.Typeable (Typeable)
import Data.Word (Word8)
-- Instances for Haskell built-ins.
instance Serialize Day where
put = put . toGregorian
get = do
(a,b,c) <- get
return $ fromGregorian a b c
-- Projects.
type ProjectId = GUID
data Project = DefaultProject
| ActiveProject { projectName :: Text
, projectCustomer :: Text
}
deriving (Typeable, Eq, Show)
instance Serialize Project where
put DefaultProject = do
put (0 :: Word8)
put (ActiveProject pn pc) = do
put (1 :: Word8)
put $ encodeUtf8 pn
put $ encodeUtf8 pc
get = do
i :: Word8 <- get
case i of
0 -> return DefaultProject
1 -> do
pn <- liftM decodeUtf8 get
pc <- liftM decodeUtf8 get
return $ ActiveProject pn pc
_ ->
fail $ "Cannot decode project state" ++ show i
instance Aggregate Project where
encodeAggregate = encode
decodeAggregate s =
case decode s of
Left e -> error e
Right a -> a
instance Default Project where
def = DefaultProject
-- Tasks.
type TaskId = GUID
data Task = NewTask
| ActiveTask { taskProjectId :: ProjectId
, taskShortDescription :: Text
, taskLongDescription :: Text
, taskWorkUnits :: Map Day WorkUnit
}
deriving (Typeable, Eq, Show)
instance Serialize Task where
put NewTask = do
put (0 :: Word8)
put (ActiveTask tpid tsd tld twu) = do
put (1 :: Word8)
put tpid
put $ encodeUtf8 tsd
put $ encodeUtf8 tld
put twu
get = do
i :: Word8 <- get
case i of
0 -> return NewTask
1 -> do
tpid <- get
tsd <- liftM decodeUtf8 get
tld <- liftM decodeUtf8 get
twu <- get
return $ ActiveTask tpid tsd tld twu
_ ->
fail $ "Cannot decode task state: " ++ show i
instance Aggregate Task where
encodeAggregate = encode
decodeAggregate s =
case decode s of
Left e -> error e
Right a -> a
instance Default Task where
def = NewTask
-- Users.
type UserId = GUID
data User = UncreatedUser
| ActiveUser { auUserName :: Text
, auLastName :: Text
, auFirstName :: Text
}
deriving (Typeable, Eq, Show)
instance Serialize User where
put UncreatedUser = do
put $ (0 :: Word8)
put (ActiveUser auun auln aufn) = do
put $ (1 :: Word8)
put $ encodeUtf8 auun
put $ encodeUtf8 auln
put $ encodeUtf8 aufn
get = do
i :: Word8 <- get
case i of
0 -> return UncreatedUser
1 -> do
auun <- liftM decodeUtf8 get
auln <- liftM decodeUtf8 get
aufn <- liftM decodeUtf8 get
return $ ActiveUser auun auln aufn
_ ->
fail $ "Cannot decode user state: " ++ show i
instance Aggregate User where
encodeAggregate = encode
decodeAggregate s =
case decode s of
Left e -> error e
Right a -> a
instance Default User where
def = UncreatedUser
-- Work Units (NOT aggregates!)
data WorkUnit = WorkUnit { workUnitId :: GUID
, workUnitComment :: Text
, workUnitDuration :: Integer
, workUnitUser :: UserId
}
deriving (Eq, Show)
instance Serialize WorkUnit where
put (WorkUnit wuid wuc wud wuu) = do
put $ wuid
put $ encodeUtf8 wuc
put wud
put wuu
get = do
wuid <- get
wuc <- liftM decodeUtf8 get
wud <- get
wuu <- get
return $ WorkUnit wuid wuc wud wuu