aboutsummaryrefslogtreecommitdiff
path: root/server/src/Controller/Payment.hs
blob: f685f2e5ef3b76e3bab9860c002e26e8732389dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
module Controller.Payment
  ( list
  , listPaymentCategories
  , create
  , edit
  , delete
  ) where

import           Control.Monad.IO.Class      (liftIO)
import qualified Data.Map                    as M
import qualified Data.Time.Clock             as Clock
import           Data.Validation             (Validation (Failure, Success))
import qualified Network.HTTP.Types.Status   as Status
import           Web.Scotty                  (ActionM)
import qualified Web.Scotty                  as S

import           Common.Model                (Category (..),
                                              CreatePaymentForm (..),
                                              EditPaymentForm (..),
                                              Frequency (Punctual),
                                              Payment (..), PaymentHeader (..),
                                              PaymentId, PaymentPage (..),
                                              SavedPayment (..), User (..))
import qualified Common.Model                as CM
import qualified Common.Msg                  as Msg
import qualified Controller.Helper           as ControllerHelper
import           Model.CreatePayment         (CreatePayment (..))
import           Model.EditPayment           (EditPayment (..))
import qualified Model.Query                 as Query
import qualified Persistence.Category        as CategoryPersistence
import qualified Persistence.Income          as IncomePersistence
import qualified Persistence.Payment         as PaymentPersistence
import qualified Persistence.PaymentCategory as PaymentCategoryPersistence
import qualified Persistence.User            as UserPersistence
import qualified Secure
import qualified Util.List                   as L
import qualified Validation.Payment          as PaymentValidation

list :: Int -> Int -> ActionM ()
list page perPage =
  Secure.loggedAction (\_ -> do
    currentTime <- liftIO Clock.getCurrentTime
    (liftIO . Query.run $ do
      count <- PaymentPersistence.count
      payments <- PaymentPersistence.listActivePage page perPage
      paymentCategories <- PaymentCategoryPersistence.list

      users <- UserPersistence.list
      incomes <- IncomePersistence.listAll
      allPayments <- PaymentPersistence.listActive Punctual

      let exceedingPayers = CM.getExceedingPayers currentTime users incomes allPayments

          repartition =
            M.fromList
              . map (\(u, xs) -> (u, sum . map snd $ xs))
              . L.groupBy fst
              . map (\p -> (_payment_user p, _payment_cost p))
              $ allPayments

          header = PaymentHeader
            { _paymentHeader_exceedingPayers = exceedingPayers
            , _paymentHeader_repartition     = repartition
            }

      return $ PaymentPage header payments paymentCategories count) >>= S.json
  )

listPaymentCategories :: ActionM ()
listPaymentCategories =
  Secure.loggedAction (\_ ->
    (liftIO . Query.run $ PaymentCategoryPersistence.list) >>= S.json
  )

create :: CreatePaymentForm -> ActionM ()
create form =
  Secure.loggedAction (\user ->
    (liftIO . Query.run $ do
      cs <- map _category_id <$> CategoryPersistence.list
      case PaymentValidation.createPayment cs form of
        Success (CreatePayment name cost date category frequency) -> do
          pc <- PaymentCategoryPersistence.save name category
          p <- PaymentPersistence.create (_user_id user) name cost date frequency
          return . Right $ SavedPayment p pc
        Failure validationError ->
          return $ Left validationError
    ) >>= ControllerHelper.jsonOrBadRequest
  )

edit :: EditPaymentForm -> ActionM ()
edit form =
  Secure.loggedAction (\user ->
    (liftIO . Query.run $ do
      cs <- map _category_id <$> CategoryPersistence.list
      case PaymentValidation.editPayment cs form of
        Success (EditPayment paymentId name cost date category frequency) -> do
          editedPayment <- PaymentPersistence.edit (_user_id user) paymentId name cost date frequency
          case editedPayment of
            Just (old, new) -> do
              pc <- PaymentCategoryPersistence.save name category
              PaymentCategoryPersistence.deleteIfUnused (_payment_name old)
              return . Right $ SavedPayment new pc
            Nothing ->
              return . Left $ Msg.get Msg.Error_PaymentEdit
        Failure validationError ->
          return $ Left validationError
    ) >>= ControllerHelper.jsonOrBadRequest
  )

delete :: PaymentId -> ActionM ()
delete paymentId =
  Secure.loggedAction (\user -> do
    deleted <- liftIO . Query.run $ do
      payment <- PaymentPersistence.find paymentId
      case payment of
        Just p | _payment_user p == _user_id user -> do
          PaymentPersistence.delete (_user_id user) paymentId
          PaymentCategoryPersistence.deleteIfUnused (_payment_name p)
          return True
        _ ->
          return False
    if deleted then
      S.status Status.ok200
    else
      S.status Status.badRequest400
  )