module Model.Payment exposing ( perPage , Payments , Payment , PaymentId , paymentsDecoder , paymentIdDecoder , find , edit , delete , totalPayments , punctual , monthly , groupAndSortByMonth , search ) 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 List.Extra as List import Form.Validate as Validate exposing (Validation) import Model.Date exposing (dateDecoder) import Model.Frequency as Frequency exposing (Frequency(..)) 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 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" Frequency.decoder) paymentIdDecoder : Decoder PaymentId paymentIdDecoder = Decode.int find : PaymentId -> Payments -> Maybe Payment find paymentId payments = payments |> List.find (\p -> p.id == paymentId) 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)) 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)