From 1e47a7754ca38bd1a6c74765d8378caf68ce4619 Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 26 Mar 2017 21:10:42 +0200 Subject: Separate client and server watch --- src/client/Model/Payment.elm | 143 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/client/Model/Payment.elm (limited to 'src/client/Model/Payment.elm') 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") + ) -- cgit v1.2.3