module Persistence.Income ( count , list , listv2 , create , edit , delete ) where import Data.Maybe (listToMaybe) import Data.Time.Calendar (Day) import Data.Time.Clock (getCurrentTime) import Database.SQLite.Simple (FromRow (fromRow), Only (Only)) import qualified Database.SQLite.Simple as SQLite import Prelude hiding (id) 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 Count = Count Int instance FromRow Count where fromRow = Count <$> SQLite.field count :: Query Int count = Query (\conn -> (\[Count n] -> n) <$> SQLite.query_ conn "SELECT COUNT(*) FROM income WHERE deleted_at IS NULL" ) list :: Query [Income] list = Query (\conn -> map (\(Row i) -> i) <$> SQLite.query_ conn "SELECT * FROM income WHERE deleted_at IS NULL" ) listv2 :: Int -> Int -> Query [Income] listv2 page perPage = Query (\conn -> map (\(Row i) -> i) <$> SQLite.query conn "SELECT * FROM income WHERE deleted_at IS NULL ORDER BY date DESC LIMIT ? OFFSET ?" (perPage, (page - 1) * perPage) ) create :: UserId -> Day -> Int -> Query Income create userId date amount = Query (\conn -> do createdAt <- getCurrentTime SQLite.execute conn "INSERT INTO income (user_id, date, amount, created_at) VALUES (?, ?, ?, ?)" (userId, date, amount, createdAt) incomeId <- SQLite.lastInsertRowId conn return $ Income { _income_id = incomeId , _income_userId = userId , _income_date = date , _income_amount = amount , _income_createdAt = createdAt , _income_editedAt = Nothing , _income_deletedAt = Nothing } ) edit :: UserId -> IncomeId -> Day -> Int -> Query (Maybe Income) edit userId incomeId incomeDate incomeAmount = Query (\conn -> do mbIncome <- fmap (\(Row i) -> i) . listToMaybe <$> SQLite.query conn "SELECT * FROM income WHERE id = ?" (Only incomeId) case mbIncome of Just income -> do currentTime <- getCurrentTime SQLite.execute conn "UPDATE income SET edited_at = ?, date = ?, amount = ? WHERE id = ? AND user_id = ?" (currentTime, incomeDate, incomeAmount, incomeId, userId) return . Just $ Income { _income_id = incomeId , _income_userId = userId , _income_date = incomeDate , _income_amount = incomeAmount , _income_createdAt = _income_createdAt income , _income_editedAt = Just currentTime , _income_deletedAt = Nothing } Nothing -> return Nothing ) delete :: UserId -> PaymentId -> Query () delete userId paymentId = Query (\conn -> SQLite.execute conn "UPDATE income SET deleted_at = datetime('now') WHERE id = ? AND user_id = ?" (paymentId, userId) )