aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoris2016-03-27 17:36:33 +0200
committerJoris2016-03-27 17:59:32 +0200
commit869bab77e93e2a6c776a4b1fc35ef0fd5df22f5f (patch)
tree917a9e871eff1c487da63ea2407234d7e3829dda /src
parenta8882071da12cbb5b0bf2f003322e42e181b0c82 (diff)
downloadbudget-869bab77e93e2a6c776a4b1fc35ef0fd5df22f5f.tar.gz
budget-869bab77e93e2a6c776a4b1fc35ef0fd5df22f5f.tar.bz2
budget-869bab77e93e2a6c776a4b1fc35ef0fd5df22f5f.zip
Compute payers client side rather than server side
Diffstat (limited to 'src')
-rw-r--r--src/client/elm/Model/Action/AccountAction.elm4
-rw-r--r--src/client/elm/Model/Income.elm65
-rw-r--r--src/client/elm/Model/Init.elm4
-rw-r--r--src/client/elm/Model/Payer.elm78
-rw-r--r--src/client/elm/Model/Payment.elm8
-rw-r--r--src/client/elm/Model/User.elm6
-rw-r--r--src/client/elm/Model/View/LoggedIn/Account.elm31
-rw-r--r--src/client/elm/Model/View/LoggedInView.elm2
-rw-r--r--src/client/elm/Server.elm8
-rw-r--r--src/client/elm/Update/LoggedIn.elm36
-rw-r--r--src/client/elm/Update/LoggedIn/Account.elm23
-rw-r--r--src/client/elm/View/LoggedIn/Account.elm2
-rw-r--r--src/server/Controller/Income.hs31
-rw-r--r--src/server/Controller/Payer.hs20
-rw-r--r--src/server/Controller/User.hs28
-rw-r--r--src/server/Json.hs10
-rw-r--r--src/server/Main.hs8
-rw-r--r--src/server/Model/Income.hs14
-rw-r--r--src/server/Model/Json/Income.hs6
-rw-r--r--src/server/Model/Payer.hs46
-rw-r--r--src/server/Model/Payer/Income.hs22
21 files changed, 187 insertions, 265 deletions
diff --git a/src/client/elm/Model/Action/AccountAction.elm b/src/client/elm/Model/Action/AccountAction.elm
index 520f3ab..3e156a5 100644
--- a/src/client/elm/Model/Action/AccountAction.elm
+++ b/src/client/elm/Model/Action/AccountAction.elm
@@ -5,13 +5,13 @@ module Model.Action.AccountAction
import Time exposing (Time)
import Model.User exposing (UserId)
+import Model.Income exposing (IncomeId)
type AccountAction =
NoOp
| ToggleDetail
- | UpdatePayer UserId Time Int
| ToggleIncomeEdition
| UpdateIncomeEdition String
| UpdateEditionError String
| UpdateIncome Time Int
- | ValidateUpdateIncome Time Int
+ | ValidateUpdateIncome IncomeId Time Int
diff --git a/src/client/elm/Model/Income.elm b/src/client/elm/Model/Income.elm
index 97a5652..f364a8b 100644
--- a/src/client/elm/Model/Income.elm
+++ b/src/client/elm/Model/Income.elm
@@ -1,6 +1,9 @@
module Model.Income
- ( Income
- , incomeDecoder
+ ( Incomes
+ , Income
+ , IncomeId
+ , incomesDecoder
+ , incomeIdDecoder
, incomeDefinedForAll
, cumulativeIncomesSince
) where
@@ -8,26 +11,46 @@ module Model.Income
import Json.Decode as Json exposing ((:=))
import Time exposing (Time, hour)
import List exposing (..)
+import Dict exposing (Dict)
import Model.Date exposing (timeDecoder)
-import Model.User exposing (UserId)
+import Model.User exposing (UserId, userIdDecoder)
import Utils.Maybe exposing (isJust, catMaybes, maybeToList)
+type alias Incomes = Dict IncomeId Income
+
+type alias IncomeId = Int
+
type alias Income =
- { creation : Time
+ { userId : UserId
+ , creation : Time
, amount : Int
}
+incomesDecoder : Json.Decoder Incomes
+incomesDecoder = Json.map Dict.fromList (Json.list incomeWithIdDecoder)
+
+incomeWithIdDecoder : Json.Decoder (IncomeId, Income)
+incomeWithIdDecoder =
+ Json.object2 (,)
+ ("id" := incomeIdDecoder)
+ incomeDecoder
+
+incomeIdDecoder : Json.Decoder IncomeId
+incomeIdDecoder = Json.int
+
incomeDecoder : Json.Decoder Income
incomeDecoder =
- Json.object2 Income
+ Json.object3 Income
+ ("userId" := userIdDecoder)
("creation" := timeDecoder)
("amount" := Json.int)
-incomeDefinedForAll : List (List Income) -> Maybe Time
-incomeDefinedForAll usersIncomes =
- let firstIncomes = map (head << sortBy .creation) usersIncomes
+incomeDefinedForAll : List UserId -> Incomes -> Maybe Time
+incomeDefinedForAll userIds incomes =
+ let userIncomes = List.map (\userId -> List.filter ((==) userId << .userId) << Dict.values <| incomes) userIds
+ firstIncomes = map (head << sortBy .creation) userIncomes
in if all isJust firstIncomes
then head << reverse << List.sort << map .creation << catMaybes <| firstIncomes
else Nothing
@@ -38,37 +61,39 @@ cumulativeIncomesSince currentTime since incomes =
getOrderedIncomesSince : Time -> List Income -> List Income
getOrderedIncomesSince time incomes =
- let mbStarterIncome = getIncomesAt time incomes
+ let mbStarterIncome = getIncomeAt time incomes
orderedIncomesSince = filter (\income -> income.creation >= time) incomes
in (maybeToList mbStarterIncome) ++ orderedIncomesSince
-getIncomesAt : Time -> List Income -> Maybe Income
-getIncomesAt time incomes =
+getIncomeAt : Time -> List Income -> Maybe Income
+getIncomeAt time incomes =
case incomes of
[x] ->
if x.creation < time
- then Just { creation = time, amount = x.amount }
+ then Just { userId = x.userId, creation = time, amount = x.amount }
else Nothing
x1 :: x2 :: xs ->
if x1.creation < time && x2.creation > time
- then Just { creation = time, amount = x2.amount }
- else getIncomesAt time (x2 :: xs)
+ then Just { userId = x2.userId, creation = time, amount = x2.amount }
+ else getIncomeAt time (x2 :: xs)
[] ->
Nothing
cumulativeIncome : Time -> List Income -> Int
cumulativeIncome currentTime incomes =
- getIncomesWithDuration (incomes ++ [{ creation = currentTime, amount = 0 }])
+ getIncomesWithDuration currentTime (List.sortBy .creation incomes)
|> map durationIncome
|> sum
-getIncomesWithDuration : List Income -> List (Float, Int)
-getIncomesWithDuration incomes =
+getIncomesWithDuration : Time -> List Income -> List (Float, Int)
+getIncomesWithDuration currentTime incomes =
case incomes of
- (income1 :: income2 :: xs) ->
- (income2.creation - income1.creation, income1.amount) :: (getIncomesWithDuration (income2 :: xs))
- _ ->
+ [] ->
[]
+ [income] ->
+ [(currentTime - income.creation, income.amount)]
+ (income1 :: income2 :: xs) ->
+ (income2.creation - income1.creation, income1.amount) :: (getIncomesWithDuration currentTime (income2 :: xs))
durationIncome : (Float, Int) -> Int
durationIncome (duration, income) =
diff --git a/src/client/elm/Model/Init.elm b/src/client/elm/Model/Init.elm
index 490321b..d9dbc36 100644
--- a/src/client/elm/Model/Init.elm
+++ b/src/client/elm/Model/Init.elm
@@ -3,7 +3,7 @@ module Model.Init
) where
import Model.Payment exposing (Payments)
-import Model.Payer exposing (Payers)
+import Model.Income exposing (Incomes)
import Model.User exposing (Users, UserId)
type alias Init =
@@ -12,5 +12,5 @@ type alias Init =
, payments : Payments
, monthlyPayments : Payments
, paymentsCount : Int
- , payers : Payers
+ , incomes : Incomes
}
diff --git a/src/client/elm/Model/Payer.elm b/src/client/elm/Model/Payer.elm
index f39a612..9ae1dfa 100644
--- a/src/client/elm/Model/Payer.elm
+++ b/src/client/elm/Model/Payer.elm
@@ -2,8 +2,6 @@ module Model.Payer
( Payers
, Payer
, ExceedingPayer
- , payersDecoder
- , updatePayers
, getOrderedExceedingPayers
) where
@@ -12,8 +10,10 @@ import Dict exposing (..)
import List
import Maybe
import Time exposing (Time)
+import Date
-import Model.User exposing (UserId, userIdDecoder)
+import Model.Payment exposing (Payments, totalPayments)
+import Model.User exposing (Users, UserId, userIdDecoder)
import Model.Income exposing (..)
import Utils.Dict exposing (mapValues)
@@ -27,54 +27,22 @@ type alias Payer =
, incomes : List Income
}
-payersDecoder : Decoder Payers
-payersDecoder = Json.map Dict.fromList (list payerDecoder)
-
-payerDecoder : Decoder (UserId, Payer)
-payerDecoder =
- object2 (,)
- ("userId" := userIdDecoder)
- (object3 Payer
- ("preIncomePaymentSum" := int)
- ("postIncomePaymentSum" := int)
- ("incomes" := list incomeDecoder))
-
-updatePayers : Payers -> UserId -> Time -> Int -> Payers
-updatePayers payers userId creation amountDiff =
- payers
- |> Dict.update userId (\mbPayer ->
- case mbPayer of
- Just payer ->
- let postIncome =
- payersIncomeDefinedForAll payers
- |> Maybe.map (\date -> creation > date)
- |> Maybe.withDefault False
- in if postIncome
- then
- Just { payer | postIncomePaymentSum = payer.postIncomePaymentSum + amountDiff }
- else
- Just { payer | preIncomePaymentSum = payer.preIncomePaymentSum + amountDiff }
- Nothing ->
- Nothing
- )
-
type alias ExceedingPayer =
{ userId : UserId
, amount : Int
}
-getOrderedExceedingPayers : Time -> Payers -> List ExceedingPayer
-getOrderedExceedingPayers currentTime payers =
- let exceedingPayersOnPreIncome =
+getOrderedExceedingPayers : Time -> Users -> Incomes -> Payments -> List ExceedingPayer
+getOrderedExceedingPayers currentTime users incomes payments =
+ let payers = getPayers currentTime users incomes payments
+ exceedingPayersOnPreIncome =
payers
|> mapValues .preIncomePaymentSum
|> Dict.toList
|> exceedingPayersFromAmounts
- in case payersIncomeDefinedForAll payers of
+ in case incomeDefinedForAll (Dict.keys users) incomes of
Just since ->
- let postPaymentPayers =
- payers
- |> mapValues (getPostPaymentPayer currentTime since)
+ let postPaymentPayers = mapValues (getPostPaymentPayer currentTime since) payers
mbMaxRatio =
postPaymentPayers
|> Dict.toList
@@ -91,9 +59,31 @@ getOrderedExceedingPayers currentTime payers =
Nothing ->
exceedingPayersOnPreIncome
-payersIncomeDefinedForAll : Payers -> Maybe Time
-payersIncomeDefinedForAll payers =
- incomeDefinedForAll (List.map (.incomes << snd) << Dict.toList <| payers)
+getPayers : Time -> Users -> Incomes -> Payments -> Payers
+getPayers currentTime users incomes payments =
+ let incomesDefined = incomeDefinedForAll (Dict.keys users) incomes
+ in Dict.keys users
+ |> List.map (\userId ->
+ ( userId
+ , { preIncomePaymentSum =
+ totalPayments
+ (\p -> (Date.toTime p.creation) < (Maybe.withDefault currentTime incomesDefined))
+ userId
+ payments
+ , postIncomePaymentSum =
+ totalPayments
+ (\p ->
+ case incomesDefined of
+ Nothing -> False
+ Just t -> (Date.toTime p.creation) >= t
+ )
+ userId
+ payments
+ , incomes = List.filter ((==) userId << .userId) (Dict.values incomes)
+ }
+ )
+ )
+ |> Dict.fromList
exceedingPayersFromAmounts : List (UserId, Int) -> List ExceedingPayer
exceedingPayersFromAmounts userAmounts =
diff --git a/src/client/elm/Model/Payment.elm b/src/client/elm/Model/Payment.elm
index 31aba1d..80579e2 100644
--- a/src/client/elm/Model/Payment.elm
+++ b/src/client/elm/Model/Payment.elm
@@ -7,6 +7,7 @@ module Model.Payment
, paymentIdDecoder
, deletePayment
, PaymentFrequency(..)
+ , totalPayments
) where
import Date exposing (..)
@@ -49,3 +50,10 @@ paymentIdDecoder = Json.int
deletePayment : PaymentId -> Payments -> Payments
deletePayment paymentId = List.filter (((/=) paymentId) << .id)
+
+totalPayments : (Payment -> Bool) -> UserId -> Payments -> Int
+totalPayments paymentFilter userId payments =
+ payments
+ |> List.filter (\payment -> paymentFilter payment && payment.userId == userId)
+ |> List.map .cost
+ |> List.sum
diff --git a/src/client/elm/Model/User.elm b/src/client/elm/Model/User.elm
index 1412913..aac5dd5 100644
--- a/src/client/elm/Model/User.elm
+++ b/src/client/elm/Model/User.elm
@@ -29,15 +29,15 @@ userWithIdDecoder =
("id" := userIdDecoder)
userDecoder
+userIdDecoder : Json.Decoder UserId
+userIdDecoder = Json.int
+
userDecoder : Json.Decoder User
userDecoder =
Json.object2 User
("name" := Json.string)
("email" := Json.string)
-userIdDecoder : Json.Decoder UserId
-userIdDecoder = Json.int
-
getUserName : Users -> UserId -> Maybe String
getUserName users userId =
Dict.get userId users
diff --git a/src/client/elm/Model/View/LoggedIn/Account.elm b/src/client/elm/Model/View/LoggedIn/Account.elm
index d03d84f..ec75397 100644
--- a/src/client/elm/Model/View/LoggedIn/Account.elm
+++ b/src/client/elm/Model/View/LoggedIn/Account.elm
@@ -14,40 +14,33 @@ import String
import Utils.Dict exposing (mapValues)
import Model.Translations exposing (..)
-import Model.Payer exposing (..)
+import Model.Income exposing (..)
import Model.User exposing (UserId)
type alias Account =
{ me : UserId
- , payers : Payers
+ , incomes : Incomes
, visibleDetail : Bool
, incomeEdition : Maybe IncomeEdition
}
-initAccount : UserId -> Payers -> Account
-initAccount me payers =
+initAccount : UserId -> Incomes -> Account
+initAccount me incomes =
{ me = me
- , payers =
- payers
- |> mapValues
- (\payer ->
- { payer | incomes = List.sortBy .creation payer.incomes }
- )
+ , incomes = incomes
, visibleDetail = False
, incomeEdition = Nothing
}
getCurrentIncome : Account -> Maybe Int
getCurrentIncome account =
- case Dict.get account.me account.payers of
- Just payer ->
- payer.incomes
- |> List.sortBy .creation
- |> List.reverse
- |> List.head
- |> Maybe.map .amount
- Nothing ->
- Nothing
+ account.incomes
+ |> Dict.filter (\_ income -> income.userId == account.me)
+ |> Dict.values
+ |> List.sortBy .creation
+ |> List.reverse
+ |> List.head
+ |> Maybe.map .amount
type alias IncomeEdition =
{ income : String
diff --git a/src/client/elm/Model/View/LoggedInView.elm b/src/client/elm/Model/View/LoggedInView.elm
index 2df3525..e33c58b 100644
--- a/src/client/elm/Model/View/LoggedInView.elm
+++ b/src/client/elm/Model/View/LoggedInView.elm
@@ -28,7 +28,7 @@ initLoggedInView init =
{ users = init.users
, add = initAddPayment Punctual
, monthly = initMonthly init.monthlyPayments
- , account = initAccount init.me init.payers
+ , account = initAccount init.me init.incomes
, payments = init.payments
, paymentsCount = init.paymentsCount
, paymentEdition = Nothing
diff --git a/src/client/elm/Server.elm b/src/client/elm/Server.elm
index c1fb445..314ca01 100644
--- a/src/client/elm/Server.elm
+++ b/src/client/elm/Server.elm
@@ -17,7 +17,7 @@ import Time exposing (Time)
import Utils.Http exposing (..)
import Model.Payment exposing (..)
-import Model.Payer exposing (Payers, payersDecoder)
+import Model.Income exposing (incomesDecoder, incomeIdDecoder, IncomeId)
import Model.User exposing (Users, usersDecoder, UserId, userIdDecoder)
import Model.Init exposing (Init)
@@ -28,7 +28,7 @@ init =
`Task.andMap` (Http.get paymentsDecoder "/payments")
`Task.andMap` (Http.get paymentsDecoder "/monthlyPayments")
`Task.andMap` (Http.get ("number" := Json.int) "/payments/count")
- `Task.andMap` (Http.get payersDecoder "/payers")
+ `Task.andMap` (Http.get incomesDecoder "/incomes")
signIn : String -> Task Http.Error ()
signIn email =
@@ -45,10 +45,10 @@ deletePayment payment frequency =
post ("payment/delete?id=" ++ (toString payment.id))
|> Task.map (always ())
-setIncome : Time -> Int -> Task Http.Error ()
+setIncome : Time -> Int -> Task Http.Error IncomeId
setIncome currentTime amount =
post ("/income?amount=" ++ (toString amount))
- |> Task.map (always ())
+ |> flip Task.andThen (decodeHttpValue <| "id" := incomeIdDecoder)
signOut : Task Http.Error ()
signOut =
diff --git a/src/client/elm/Update/LoggedIn.elm b/src/client/elm/Update/LoggedIn.elm
index dfc2a1b..300c63a 100644
--- a/src/client/elm/Update/LoggedIn.elm
+++ b/src/client/elm/Update/LoggedIn.elm
@@ -71,17 +71,15 @@ updateLoggedIn model action loggedInView =
newAdd = initAddPayment frequency
in case frequency of
Punctual ->
- let (newAccount, accountEffects) =
- updateAccount (Account.UpdatePayer loggedInView.account.me model.currentTime cost) loggedInView.account
- in ( { loggedInView
- | currentPage = 1
- , add = newAdd
- , account = newAccount
- , payments = newPayment :: loggedInView.payments
- , paymentsCount = loggedInView.paymentsCount + 1
- }
- , Effects.map UpdateAccount accountEffects
- )
+ ( { loggedInView
+ | currentPage = 1
+ , add = newAdd
+ , account = loggedInView.account
+ , payments = newPayment :: loggedInView.payments
+ , paymentsCount = loggedInView.paymentsCount + 1
+ }
+ , Effects.none
+ )
Monthly ->
( { loggedInView
| add = newAdd
@@ -112,15 +110,13 @@ updateLoggedIn model action loggedInView =
, Effects.none
)
Punctual ->
- let (newAccount, accountEffects) =
- updateAccount (Account.UpdatePayer payment.userId (Date.toTime payment.creation) -payment.cost) loggedInView.account
- in ( { loggedInView
- | account = newAccount
- , payments = deletePayment payment.id loggedInView.payments
- , paymentsCount = loggedInView.paymentsCount - 1
- }
- , Effects.map UpdateAccount accountEffects
- )
+ ( { loggedInView
+ | account = loggedInView.account
+ , payments = deletePayment payment.id loggedInView.payments
+ , paymentsCount = loggedInView.paymentsCount - 1
+ }
+ , Effects.none
+ )
UpdatePage page ->
( { loggedInView | currentPage = page }
diff --git a/src/client/elm/Update/LoggedIn/Account.elm b/src/client/elm/Update/LoggedIn/Account.elm
index 1773b9a..233efa9 100644
--- a/src/client/elm/Update/LoggedIn/Account.elm
+++ b/src/client/elm/Update/LoggedIn/Account.elm
@@ -10,7 +10,6 @@ import Effects exposing (Effects)
import Server
-import Model.Payer exposing (updatePayers)
import Model.Action.AccountAction exposing (..)
import Model.View.LoggedIn.Account exposing (..)
@@ -28,11 +27,6 @@ updateAccount action account =
, Effects.none
)
- UpdatePayer userId creation amountDiff ->
- ( { account | payers = updatePayers account.payers userId creation amountDiff }
- , Effects.none
- )
-
ToggleIncomeEdition ->
( { account | incomeEdition =
if isJust account.incomeEdition
@@ -67,25 +61,14 @@ updateAccount action account =
UpdateIncome currentTime amount ->
( account
, Server.setIncome currentTime amount
- |> Task.map (always (ValidateUpdateIncome currentTime amount))
+ |> Task.map (\incomeId -> (ValidateUpdateIncome incomeId currentTime amount))
|> flip Task.onError (always <| Task.succeed NoOp)
|> Effects.task
)
- ValidateUpdateIncome currentTime amount ->
+ ValidateUpdateIncome incomeId currentTime amount ->
( { account
- | payers =
- account.payers
- |> Dict.update account.me (\mbPayer ->
- case mbPayer of
- Just payer ->
- Just
- { payer
- | incomes = payer.incomes ++ [{ creation = currentTime, amount = amount }]
- }
- Nothing ->
- Nothing
- )
+ | incomes = Dict.insert incomeId { userId = account.me, creation = currentTime, amount = amount } account.incomes
, incomeEdition = Nothing
}
, Effects.none
diff --git a/src/client/elm/View/LoggedIn/Account.elm b/src/client/elm/View/LoggedIn/Account.elm
index d8884f1..5bbf73e 100644
--- a/src/client/elm/View/LoggedIn/Account.elm
+++ b/src/client/elm/View/LoggedIn/Account.elm
@@ -48,7 +48,7 @@ exceedingPayers address model loggedInView =
[ class "header"
, onClick address (UpdateLoggedIn << UpdateAccount <| ToggleDetail)
]
- ( (List.map (exceedingPayer model loggedInView) (getOrderedExceedingPayers model.currentTime loggedInView.account.payers))
+ ( (List.map (exceedingPayer model loggedInView) (getOrderedExceedingPayers model.currentTime loggedInView.users loggedInView.account.incomes loggedInView.payments))
++ [ expand ExpandDown loggedInView.account.visibleDetail ]
)
diff --git a/src/server/Controller/Income.hs b/src/server/Controller/Income.hs
new file mode 100644
index 0000000..51861d3
--- /dev/null
+++ b/src/server/Controller/Income.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Controller.Income
+ ( getIncomes
+ , setIncome
+ ) where
+
+import Web.Scotty
+
+import Control.Monad.IO.Class (liftIO)
+
+import Database.Persist
+
+import qualified Secure
+
+import Json (jsonId)
+
+import Model.Database
+import qualified Model.Income as Income
+
+getIncomes :: ActionM ()
+getIncomes =
+ Secure.loggedAction (\_ ->
+ (liftIO $ map Income.getJsonIncome <$> runDb Income.getIncomes) >>= json
+ )
+
+setIncome :: Int -> ActionM ()
+setIncome amount =
+ Secure.loggedAction (\user -> do
+ (liftIO . runDb $ Income.setIncome (entityKey user) amount) >>= jsonId
+ )
diff --git a/src/server/Controller/Payer.hs b/src/server/Controller/Payer.hs
deleted file mode 100644
index 70760ae..0000000
--- a/src/server/Controller/Payer.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Controller.Payer
- ( getPayers
- ) where
-
-import Web.Scotty
-
-import Control.Monad.IO.Class (liftIO)
-
-import Model.Database
-import qualified Model.Payer as P
-
-import Secure (loggedAction)
-
-getPayers :: ActionM ()
-getPayers =
- Secure.loggedAction (\_ ->
- (liftIO $ runDb P.getPayers) >>= json
- )
diff --git a/src/server/Controller/User.hs b/src/server/Controller/User.hs
index 420a2d9..1baab18 100644
--- a/src/server/Controller/User.hs
+++ b/src/server/Controller/User.hs
@@ -3,27 +3,16 @@
module Controller.User
( getUsers
, whoAmI
- , getIncome
- , setIncome
) where
import Web.Scotty
-import Network.HTTP.Types.Status (ok200)
-
import Control.Monad.IO.Class (liftIO)
-import Database.Persist
-
-import qualified Data.Aeson.Types as Json
-
import qualified Secure
-import Json (jsonObject)
-
import Model.Database
import qualified Model.User as U
-import qualified Model.Income as I
getUsers :: ActionM ()
getUsers =
@@ -36,20 +25,3 @@ whoAmI =
Secure.loggedAction (\user ->
json (U.getJsonUser user)
)
-
-getIncome :: ActionM ()
-getIncome =
- Secure.loggedAction (\user -> do
- mbIncome <- liftIO . runDb . I.getIncome $ entityKey user
- case mbIncome of
- Just income ->
- jsonObject [("income", Json.Number . fromIntegral . incomeAmount $ income)]
- Nothing ->
- jsonObject []
- )
-
-setIncome :: Int -> ActionM ()
-setIncome amount =
- Secure.loggedAction (\user ->
- (liftIO . runDb $ I.setIncome (entityKey user) amount) >> status ok200
- )
diff --git a/src/server/Json.hs b/src/server/Json.hs
index a2f1ef5..408742a 100644
--- a/src/server/Json.hs
+++ b/src/server/Json.hs
@@ -1,7 +1,9 @@
{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleContexts #-}
module Json
( jsonObject
+ , jsonId
) where
import Web.Scotty
@@ -10,5 +12,13 @@ import qualified Data.Aeson.Types as Json
import qualified Data.HashMap.Strict as M
import Data.Text (Text)
+import Database.Persist
+import Database.Persist.Sqlite
+
+import Model.Database
+
jsonObject :: [(Text, Json.Value)] -> ActionM ()
jsonObject = json . Json.Object . M.fromList
+
+jsonId :: (ToBackendKey SqlBackend a) => Key a -> ActionM ()
+jsonId key = json . Json.Object . M.fromList $ [("id", Json.Number . fromIntegral . keyToInt64 $ key)]
diff --git a/src/server/Main.hs b/src/server/Main.hs
index 5688324..4f74f8e 100644
--- a/src/server/Main.hs
+++ b/src/server/Main.hs
@@ -15,7 +15,7 @@ import Controller.Index
import Controller.SignIn
import Controller.Payment
import Controller.User
-import Controller.Payer
+import Controller.Income
import Model.Database (runMigrations)
import Model.Frequency
@@ -58,7 +58,7 @@ main = do
get "/users" getUsers
get "/whoAmI" whoAmI
- get "/income" getIncome
+ get "/incomes" getIncomes
post "/income" $ do
amount <- param "amount" :: ActionM Int
setIncome amount
@@ -80,7 +80,3 @@ main = do
deletePayment paymentId
get "/payments/count" getPaymentsCount
-
- -- Payers
-
- get "/payers" getPayers
diff --git a/src/server/Model/Income.hs b/src/server/Model/Income.hs
index 70b9149..2177617 100644
--- a/src/server/Model/Income.hs
+++ b/src/server/Model/Income.hs
@@ -1,5 +1,5 @@
module Model.Income
- ( getIncome
+ ( getJsonIncome
, getFirstIncome
, getIncomes
, setIncome
@@ -12,13 +12,15 @@ import Control.Monad.IO.Class (liftIO)
import Database.Persist
import Model.Database
+import qualified Model.Json.Income as Json
-getIncome :: UserId -> Persist (Maybe Income)
-getIncome userId =
- fmap entityVal <$> selectFirst [IncomeUserId ==. userId] [Desc IncomeCreation]
+getJsonIncome :: Entity Income -> Json.Income
+getJsonIncome incomeEntity =
+ Json.Income (entityKey incomeEntity) (incomeUserId income) (incomeCreation income) (incomeAmount income)
+ where income = entityVal incomeEntity
-getIncomes :: Persist [Income]
-getIncomes = map entityVal <$> selectList [] []
+getIncomes :: Persist [Entity Income]
+getIncomes = selectList [] []
getFirstIncome :: UserId -> Persist (Maybe Income)
getFirstIncome userId =
diff --git a/src/server/Model/Json/Income.hs b/src/server/Model/Json/Income.hs
index 4549ca5..6ad331a 100644
--- a/src/server/Model/Json/Income.hs
+++ b/src/server/Model/Json/Income.hs
@@ -9,8 +9,12 @@ import GHC.Generics
import Data.Aeson
import Data.Time.Clock (UTCTime)
+import Model.Database (IncomeId, UserId)
+
data Income = Income
- { creation :: UTCTime
+ { id :: IncomeId
+ , userId :: UserId
+ , creation :: UTCTime
, amount :: Int
} deriving (Show, Generic)
diff --git a/src/server/Model/Payer.hs b/src/server/Model/Payer.hs
deleted file mode 100644
index 3893765..0000000
--- a/src/server/Model/Payer.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-module Model.Payer
- ( getPayers
- )
- where
-
-import Control.Monad.IO.Class (liftIO)
-
-import Data.Time.Clock (getCurrentTime)
-import Data.List (find)
-import Data.Maybe (fromMaybe, fromMaybe)
-
-import Database.Persist
-
-import Model.Database
-import Model.Payer.Payment (getTotalPaymentsBefore, getTotalPaymentsAfter)
-import Model.Payer.Income (incomeDefinedForAll)
-import Model.User (getUsers)
-import Model.Income (getIncomes)
-
-import qualified Model.Json.Payer as Json
-import qualified Model.Json.Income as Json
-
-getPayers :: Persist [Json.Payer]
-getPayers = do
- userIds <- map entityKey <$> getUsers
- incomes <- getIncomes
- now <- liftIO getCurrentTime
- incomeIsDefined <- fromMaybe now <$> incomeDefinedForAll
- preIncomePaymentSums <- getTotalPaymentsBefore incomeIsDefined
- postIncomePaymentSums <- getTotalPaymentsAfter incomeIsDefined
- return $ map (getPayer incomes preIncomePaymentSums postIncomePaymentSums) userIds
-
-getPayer :: [Income] -> [(UserId, Int)] -> [(UserId, Int)] -> UserId -> Json.Payer
-getPayer incomes preIncomePaymentSums postIncomePaymentSums userId =
- Json.Payer
- { Json.userId = userId
- , Json.preIncomePaymentSum = findOrDefault userId 0 preIncomePaymentSums
- , Json.postIncomePaymentSum = findOrDefault userId 0 postIncomePaymentSums
- , Json.incomes =
- map (\income -> Json.Income (incomeCreation income) (incomeAmount income))
- . filter ((==) userId . incomeUserId)
- $ incomes
- }
-
-findOrDefault :: (Eq a) => a -> b -> [(a, b)] -> b
-findOrDefault a b = fromMaybe b . fmap snd . find ((==) a . fst)
diff --git a/src/server/Model/Payer/Income.hs b/src/server/Model/Payer/Income.hs
deleted file mode 100644
index f4bc9fd..0000000
--- a/src/server/Model/Payer/Income.hs
+++ /dev/null
@@ -1,22 +0,0 @@
-module Model.Payer.Income
- ( incomeDefinedForAll
- ) where
-
-import Data.Time.Clock (UTCTime)
-import Data.List (sort)
-import Data.Maybe
-
-import Database.Persist
-
-import Model.Database
-import Model.User (getUsers)
-import Model.Income (getFirstIncome)
-
-incomeDefinedForAll :: Persist (Maybe UTCTime)
-incomeDefinedForAll = do
- userIds <- map entityKey <$> getUsers
- firstIncomes <- mapM getFirstIncome userIds
- return $
- if all isJust firstIncomes
- then listToMaybe . reverse . sort . map incomeCreation . catMaybes $ firstIncomes
- else Nothing