{-# OPTIONS_GHC -fno-warn-orphans #-} module Model.Payment ( Payment(..) , find , listActive , listPunctual , listActiveMonthlyOrderedByName , create , createMany , editOwn , deleteOwn ) where import Data.Maybe (listToMaybe) import Data.Text (Text) import qualified Data.Text as T import Data.Time.Calendar (Day) import Data.Time.Clock (getCurrentTime) import Database.SQLite.Simple (FromRow (fromRow), Only (Only), ToRow) import qualified Database.SQLite.Simple as SQLite import Database.SQLite.Simple.ToField (ToField (toField)) import Prelude hiding (id) import Common.Model (Frequency (..), Payment (..), PaymentId, UserId) import Model.Frequency () import Model.Query (Query (Query)) import Resource (Resource, resourceCreatedAt, resourceDeletedAt, resourceEditedAt) instance Resource Payment where resourceCreatedAt = _payment_createdAt resourceEditedAt = _payment_editedAt resourceDeletedAt = _payment_deletedAt instance FromRow Payment where fromRow = Payment <$> SQLite.field <*> SQLite.field <*> SQLite.field <*> SQLite.field <*> SQLite.field <*> SQLite.field <*> SQLite.field <*> SQLite.field <*> SQLite.field instance ToRow Payment where toRow p = [ toField (_payment_user p) , toField (_payment_name p) , toField (_payment_cost p) , toField (_payment_date p) , toField (_payment_frequency p) , toField (_payment_createdAt p) ] find :: PaymentId -> Query (Maybe Payment) find paymentId = Query (\conn -> listToMaybe <$> SQLite.query conn "SELECT * FROM payment WHERE id = ?" (Only paymentId) ) listActive :: Query [Payment] listActive = Query (\conn -> SQLite.query_ conn "SELECT * FROM payment WHERE deleted_at IS NULL" ) listPunctual :: Query [Payment] listPunctual = Query (\conn -> SQLite.query conn (SQLite.Query "SELECT * FROM payment WHERE frequency = ?") (Only Punctual)) listActiveMonthlyOrderedByName :: Query [Payment] listActiveMonthlyOrderedByName = Query (\conn -> SQLite.query conn (SQLite.Query $ T.intercalate " " [ "SELECT *" , "FROM payment" , "WHERE deleted_at IS NULL AND frequency = ?" , "ORDER BY name DESC" ]) (Only Monthly)) create :: UserId -> Text -> Int -> Day -> Frequency -> Query PaymentId create userId paymentName paymentCost paymentDate paymentFrequency = Query (\conn -> do now <- getCurrentTime SQLite.execute conn (SQLite.Query $ T.intercalate " " [ "INSERT INTO payment (user_id, name, cost, date, frequency, created_at)" , "VALUES (?, ?, ?, ?, ?, ?)" ]) (userId, paymentName, paymentCost, paymentDate, paymentFrequency, now) SQLite.lastInsertRowId conn ) createMany :: [Payment] -> Query () createMany payments = Query (\conn -> SQLite.executeMany conn (SQLite.Query $ T.intercalate "" [ "INSERT INTO payment (user_id, name, cost, date, frequency, created_at)" , "VALUES (?, ?, ?, ?, ?, ?)" ]) payments ) editOwn :: UserId -> PaymentId -> Text -> Int -> Day -> Frequency -> Query Bool editOwn userId paymentId paymentName paymentCost paymentDate paymentFrequency = Query (\conn -> do mbPayment <- listToMaybe <$> SQLite.query conn "SELECT * FROM payment WHERE id = ?" (Only paymentId) case mbPayment of Just payment -> if _payment_user payment == userId then do now <- getCurrentTime SQLite.execute conn (SQLite.Query $ T.intercalate " " [ "UPDATE payment" , "SET edited_at = ?," , " name = ?," , " cost = ?," , " date = ?," , " frequency = ?" , "WHERE id = ?" ]) (now, paymentName, paymentCost, paymentDate, paymentFrequency, paymentId) return True else return False Nothing -> return False ) deleteOwn :: UserId -> PaymentId -> Query Bool deleteOwn userId paymentId = Query (\conn -> do mbPayment <- listToMaybe <$> SQLite.query conn "SELECT * FROM payment WHERE id = ?" (Only paymentId) case mbPayment of Just payment -> if _payment_user payment == userId then do now <- getCurrentTime SQLite.execute conn "UPDATE payment SET deleted_at = ? WHERE id = ?" (now, paymentId) return True else return False Nothing -> return False )