From 11052951b74b9ad4b6a9412ae490086235f9154b Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 3 Jan 2021 13:40:40 +0100 Subject: Rewrite in Rust --- server/src/Persistence/Income.hs | 201 --------------------------------------- 1 file changed, 201 deletions(-) delete mode 100644 server/src/Persistence/Income.hs (limited to 'server/src/Persistence/Income.hs') diff --git a/server/src/Persistence/Income.hs b/server/src/Persistence/Income.hs deleted file mode 100644 index 1b5364c..0000000 --- a/server/src/Persistence/Income.hs +++ /dev/null @@ -1,201 +0,0 @@ -module Persistence.Income - ( listAll - , count - , list - , listModifiedSince - , create - , edit - , delete - , definedForAll - , getCumulativeIncome - ) where - -import qualified Data.List as L -import Data.Map (Map) -import qualified Data.Map as M -import qualified Data.Maybe as Maybe -import qualified Data.Text as T -import Data.Time.Calendar (Day) -import Data.Time.Clock (UTCTime) -import Data.Time.Clock (getCurrentTime) -import Database.SQLite.Simple (FromRow (fromRow), NamedParam ((:=))) -import qualified Database.SQLite.Simple as SQLite -import Prelude hiding (id, until) - -import Common.Model (Income (..), IncomeId, PaymentId, - UserId) - -import Model.Query (Query (Query)) - -newtype Row = Row Income - -instance FromRow Row where - fromRow = Row <$> (Income <$> - SQLite.field <*> - SQLite.field <*> - SQLite.field <*> - SQLite.field <*> - SQLite.field <*> - SQLite.field <*> - SQLite.field) - -data CountRow = CountRow Int - -instance FromRow CountRow where - fromRow = CountRow <$> SQLite.field - -listAll :: Query [Income] -listAll = - Query (\conn -> - map (\(Row i) -> i) <$> - SQLite.query_ - conn - "SELECT * FROM income WHERE deleted_at IS NULL ORDER BY date DESC" - ) - - -count :: Query Int -count = - Query (\conn -> - (Maybe.fromMaybe 0 . fmap (\(CountRow n) -> n) . Maybe.listToMaybe) <$> - SQLite.query_ conn "SELECT COUNT(*) FROM income WHERE deleted_at IS NULL" - ) - -list :: Int -> Int -> Query [Income] -list page perPage = - Query (\conn -> - map (\(Row i) -> i) <$> - SQLite.queryNamed - conn - "SELECT * FROM income WHERE deleted_at IS NULL ORDER BY date DESC LIMIT :limit OFFSET :offset" - [ ":limit" := perPage - , ":offset" := (page - 1) * perPage - ] - ) - -listModifiedSince :: UTCTime -> Query [Income] -listModifiedSince since = - Query (\conn -> - map (\(Row i) -> i) <$> - SQLite.queryNamed - conn - (SQLite.Query . T.intercalate " " $ - [ "SELECT *" - , "FROM income" - , "WHERE" - , "created_at >= :since" - , "OR edited_at >= :since" - , "OR deleted_at >= :since" - ]) - [ ":since" := since ] - ) - -create :: UserId -> Day -> Int -> Query () -create userId date amount = - Query (\conn -> do - createdAt <- getCurrentTime - SQLite.executeNamed - conn - "INSERT INTO income (user_id, date, amount, created_at) VALUES (:userId, :date, :amount, :createdAt)" - [ ":userId" := userId - , ":date" := date - , ":amount" := amount - , ":createdAt" := createdAt - ] - ) - -edit :: UserId -> IncomeId -> Day -> Int -> Query Bool -edit userId id date amount = - Query (\conn -> do - income <- fmap (\(Row i) -> i) . Maybe.listToMaybe <$> - SQLite.queryNamed conn "SELECT * FROM income WHERE id = :id" [ ":id" := id ] - if Maybe.isJust income then - do - currentTime <- getCurrentTime - SQLite.executeNamed - conn - "UPDATE income SET edited_at = :editedAt, date = :date, amount = :amount WHERE id = :id AND user_id = :userId" - [ ":editedAt" := currentTime - , ":date" := date - , ":amount" := amount - , ":id" := id - , ":userId" := userId - ] - return True - else - return False - ) - -delete :: UserId -> PaymentId -> Query () -delete userId id = - Query (\conn -> - SQLite.executeNamed - conn - "UPDATE income SET deleted_at = datetime('now') WHERE id = :id AND user_id = :userId" - [ ":id" := id - , ":userId" := userId - ] - ) - -data UserDayRow = UserDayRow (UserId, Day) - -instance FromRow UserDayRow where - fromRow = do - user <- SQLite.field - day <- SQLite.field - return $ UserDayRow (user, day) - -definedForAll :: [UserId] -> Query (Maybe Day) -definedForAll users = - Query (\conn -> - (fromRows . fmap (\(UserDayRow (user, day)) -> (user, day))) <$> - SQLite.query_ - conn - "SELECT user_id, MIN(date) FROM income WHERE deleted_at IS NULL GROUP BY user_id;" - ) - where - fromRows rows = - if L.sort users == L.sort (map fst rows) then - Maybe.listToMaybe . reverse . L.sort . map snd $ rows - else - Nothing - -getCumulativeIncome :: Day -> Day -> Query (Map UserId Int) -getCumulativeIncome start end = - Query (\conn -> M.fromList <$> SQLite.queryNamed conn (SQLite.Query query) parameters) - where - query = - T.intercalate "\n" $ - [ "SELECT user_id, CAST(ROUND(SUM(count)) AS INTEGER) FROM (" - , " SELECT" - , " I1.user_id," - , " ((JULIANDAY(MIN(I2.date)) - JULIANDAY(I1.date)) * I1.amount * 12 / 365) AS count" - , " FROM (" <> (selectBoundedIncomes ">" ":start") <> ") AS I1" - , " INNER JOIN (" <> (selectBoundedIncomes "<" ":end") <> ") AS I2" - , " ON I2.date > I1.date AND I2.user_id == I1.user_id" - , " GROUP BY I1.date, I1.user_id" - , ") GROUP BY user_id" - ] - - selectBoundedIncomes op param = - T.intercalate "\n" $ - [ " SELECT user_id, date, amount FROM (" - , " SELECT" - , " i.user_id, " <> param <> " AS date, i.amount" - , " FROM" - , " (SELECT id, MAX(date) AS max_date" - , " FROM income" - , " WHERE date <= " <> param <> " AND deleted_at IS NULL" - , " GROUP BY user_id) AS m" - , " INNER JOIN income AS i" - , " ON i.id = m.id AND i.date = m.max_date" - , " ) UNION" - , " SELECT user_id, date, amount" - , " FROM income" - , " WHERE date " <> op <> " " <> param <> " AND deleted_at IS NULL" - ] - - parameters = - [ ":start" := start - , ":end" := end - ] -- cgit v1.2.3