{-# LANGUAGE FlexibleInstances #-} module Model where import ClassyPrelude.Yesod import Database.Persist.Quasi import Control.Monad.Writer import Data.Text (Text) import qualified Data.Text as Text import Data.Aeson -- You can define all of your database entities in the entities file. -- You can find more information on persistent and how to declare entities -- at: -- http://www.yesodweb.com/book/persistent/ share [mkPersist sqlSettings, mkMigrate "migrateAll"] $(persistFileWith lowerCaseSettings "config/models") instance Ord Item where x `compare` y = mconcat [ (isNothing $ itemOpened x) `compare` (isNothing $ itemOpened y) , itemOpened x `compare` itemOpened y , (isNothing $ itemExpires x) `compare` (isNothing $ itemExpires y) , itemExpires x `compare` itemExpires x , itemKind x `compare` itemKind x , itemBought x `compare` itemBought x ] instance ToJSON Item where toJSON Item{..} = object $ [ "kind" .= itemKind ] ++ maybe [] (\x -> ["bought" .= x]) itemBought ++ maybe [] (\x -> ["expires" .= x]) itemExpires ++ maybe [] (\x -> ["opened" .= x]) itemOpened instance FromJSON Item where parseJSON = withObject "Item" $ \obj -> do itemKind <- obj .: "kind" let itemNormKind = normalizeKind itemKind itemBought <- obj .:? "bought" itemExpires <- obj .:? "expires" itemOpened <- obj .:? "opened" return Item{..} instance ToJSON (Entity Item) where toJSON = entityIdToJSON instance FromJSON (Entity Item) where parseJSON = entityIdFromJSON instance ToJSON Reference where toJSON Reference{..} = String referenceKind instance FromJSON Reference where parseJSON = withText "Reference" $ \referenceKind -> do let referenceNormKind = normalizeKind referenceKind return Reference{..} instance ToJSON (Entity Reference) where toJSON = keyValueEntityToJSON instance FromJSON (Entity Reference) where parseJSON = keyValueEntityFromJSON normalizeKind :: Text -> Text normalizeKind = Text.strip . Text.toCaseFold data ItemDiff = DiffKind Text | DiffBought (Maybe Day) | DiffExpires (Maybe Day) | DiffOpened (Maybe Day) newtype ItemDiffs = ItemDiffs [ItemDiff] instance FromJSON ItemDiffs where parseJSON = withObject "ItemDiff" $ \obj -> fmap ItemDiffs . execWriterT $ do tell =<< maybe [] (pure . DiffKind) <$> lift (obj .:? "kind") tell =<< maybe [] (pure . DiffBought) <$> lift (obj .:! "bought") tell =<< maybe [] (pure . DiffExpires) <$> lift (obj .:! "expires") tell =<< maybe [] (pure . DiffOpened) <$> lift (obj .:! "opened") toUpdate :: ItemDiffs -> [Update Item] toUpdate (ItemDiffs ds) = do x <- ds case x of DiffKind t -> [ ItemKind =. t , ItemNormKind =. normalizeKind t ] DiffBought d -> [ ItemBought =. d ] DiffExpires d -> [ ItemExpires =. d ] DiffOpened d -> [ ItemOpened =. d ]