aboutsummaryrefslogtreecommitdiff
path: root/src/client/Model/Payment.elm
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/Model/Payment.elm')
-rw-r--r--src/client/Model/Payment.elm143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/client/Model/Payment.elm b/src/client/Model/Payment.elm
new file mode 100644
index 0000000..f61ded8
--- /dev/null
+++ b/src/client/Model/Payment.elm
@@ -0,0 +1,143 @@
+module Model.Payment exposing
+ ( perPage
+ , Payments
+ , Payment
+ , PaymentId
+ , Frequency(..)
+ , paymentsDecoder
+ , paymentIdDecoder
+ , find
+ , edit
+ , delete
+ , totalPayments
+ , punctual
+ , monthly
+ , groupAndSortByMonth
+ , search
+ , validateFrequency
+ )
+
+import Date exposing (..)
+import Date.Extra.Core exposing (monthToInt, intToMonth)
+import Json.Decode as Decode exposing (Decoder)
+import Json.Decode.Extra as Decode
+import List
+
+import Form.Validate as Validate exposing (Validation)
+import Model.Date exposing (dateDecoder)
+import Model.User exposing (UserId, userIdDecoder)
+
+import Utils.List as List
+import Utils.Search as Search
+
+perPage : Int
+perPage = 7
+
+type alias Payments = List Payment
+
+type alias Payment =
+ { id : PaymentId
+ , name : String
+ , cost : Int
+ , date : Date
+ , userId : UserId
+ , frequency : Frequency
+ }
+
+type alias PaymentId = Int
+
+type Frequency = Punctual | Monthly
+
+paymentsDecoder : Decoder Payments
+paymentsDecoder = Decode.list paymentDecoder
+
+paymentDecoder : Decoder Payment
+paymentDecoder =
+ Decode.map6 Payment
+ (Decode.field "id" paymentIdDecoder)
+ (Decode.field "name" Decode.string)
+ (Decode.field "cost" Decode.int)
+ (Decode.field "date" dateDecoder)
+ (Decode.field "userId" userIdDecoder)
+ (Decode.field "frequency" frequencyDecoder)
+
+paymentIdDecoder : Decoder PaymentId
+paymentIdDecoder = Decode.int
+
+frequencyDecoder : Decoder Frequency
+frequencyDecoder =
+ let frequencyResult input =
+ case input of
+ "Punctual" -> Ok Punctual
+ "Monthly" -> Ok Monthly
+ _ -> Err ("Could not deduce Punctual nor Monthly from " ++ input)
+ in Decode.string |> Decode.andThen (Decode.fromResult << frequencyResult)
+
+find : PaymentId -> Payments -> Maybe Payment
+find paymentId payments =
+ payments
+ |> List.filter (\p -> p.id == paymentId)
+ |> List.head
+
+edit : Payment -> Payments -> Payments
+edit payment payments = payment :: delete payment.id payments
+
+delete : PaymentId -> Payments -> Payments
+delete 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
+
+punctual : Payments -> Payments
+punctual = List.filter ((==) Punctual << .frequency)
+
+monthly : Payments -> Payments
+monthly = List.filter ((==) Monthly << .frequency)
+
+groupAndSortByMonth : Payments -> List ((Month, Int), Payments)
+groupAndSortByMonth payments =
+ payments
+ |> List.groupBy (\payment -> (Date.year payment.date, monthToInt << Date.month <| payment.date))
+ |> List.sortBy Tuple.first
+ |> List.map (\((year, month), payments) -> ((intToMonth month, year), payments))
+ |> List.reverse
+
+search : String -> Frequency -> Payments -> Payments
+search name frequency payments =
+ payments
+ |> List.filter ((==) frequency << .frequency)
+ |> paymentSort frequency
+ |> List.filter (searchSuccess name)
+
+paymentSort : Frequency -> Payments -> Payments
+paymentSort frequency =
+ case frequency of
+ Punctual -> List.reverse << List.sortBy (Date.toTime << .date)
+ Monthly -> List.sortBy (String.toLower << .name)
+
+searchSuccess : String -> Payment -> Bool
+searchSuccess search { name, cost } =
+ let searchSuccessWord word =
+ ( String.contains (Search.format word) (Search.format name)
+ || String.contains word (toString cost)
+ )
+ in List.all searchSuccessWord (String.words search)
+
+validateFrequency : Validation String Frequency
+validateFrequency =
+ Validate.customValidation Validate.string (\str ->
+ if str == toString Punctual
+ then
+ Ok Punctual
+ else
+ if str == toString Monthly
+ then Ok Monthly
+ else Err (Validate.customError "InvalidFrequency")
+ )