IHP 1.1 is out now!

How do you deal with money?

axelbdt

Hello again!

I am looking for pointers on how to handle money/pricing.

Based on the stripe integration example, I represent the price of a Trip as an Integer, i.e the number of cents. I still want the user to read and input a decimal number with a comma (french notation). I ended up with form and processing as follows:

Controller

buildTrip trip = trip
    |> parseAndSetPrice (param "decimalPrice')
parseAndSetPrice text record =
    case readFloatWithComma text of
        Left error  -> record |> attachFailure #price error
        Right amount -> record |> set #price (eurosToCents amount)

    
readFloatWithComma :: Text -> Either Text Float
readFloatWithComma text = case text |> T.replace "," "." |> T.unpack |> reads of
    [(x, "")] -> Right x
    _         -> Left "Invalid input"

eurosToCents :: Float -> Int
eurosToCents amount = round (100 * amount)

New View

renderForm :: Trip -> Html
renderForm trip = formFor trip [hsx|
    {(numberField #price) {fieldName="decimalPrice", additionalAttributes = [("min","0"), ("step","0.01")]}}
|]

The number field prevents most of malformed input, but if there is an error in the form, the page is reloaded and the price has been multiplied by 100. Same problem when a trip is opened for edition.

So I am looking for a way to divide the #price field (in cents) before I display a decimal in the form.

I am also open to other approaches altogether (would you use a float field for the price?)

Thanks in advance