Skip to content

Commit

Permalink
Merge pull request #227 from citizennet/arthur/negative-cents
Browse files Browse the repository at this point in the history
Fix `Ocelot.Data.Currency` functions not working with negative `Cents` values
  • Loading branch information
arthurxavierx authored Mar 4, 2022
2 parents 0a4af1d + d38be6a commit e8e271c
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 6 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "purescript-ocelot",
"version": "0.33.1",
"version": "0.33.2",
"private": true,
"scripts": {
"build-all": "make build",
Expand Down
13 changes: 8 additions & 5 deletions src/Data/Currency.purs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Data.Foldable (foldr)
import Data.Int (fromString) as Int
import Data.Maybe (Maybe(..), fromMaybe, isJust)
import Data.Newtype (class Newtype, unwrap)
import Data.Ord (abs)
import Data.String (Pattern(..), Replacement(..), length, replaceAll, split, take, null)
import Data.String.CodeUnits (toCharArray, fromCharArray)
import Data.Tuple (Tuple(..), snd)
Expand Down Expand Up @@ -81,9 +82,11 @@ parseCentsFromDollarStr str = Cents <$> case split (Pattern ".") str of

-- There is one decimal; truncate the cents to 2 places and
-- add them to the dollars
[ dollars, cents ] ->
bigIntIs64Bit
=<< (+) <$> dollarsPlace dollars <*> BigInt.fromString (take 2 $ cents <> "0")
[ dollars, cents ] -> do
dollars' <- dollarsPlace dollars
cents' <- BigInt.fromString (take 2 $ cents <> "0")
let bigInt = if dollars' < zero then dollars' - cents' else dollars' + cents'
bigIntIs64Bit bigInt

-- Unable to parse
_ -> Nothing
Expand Down Expand Up @@ -115,8 +118,8 @@ parseCentsFromDollarStr str = Cents <$> case split (Pattern ".") str of
-- in dollars.
formatCentsToStrDollars :: Cents -> String
formatCentsToStrDollars (Cents n)
| BigInt.toNumber n < 10.0 = "0.0" <> BigInt.toString n
| BigInt.toNumber n < 100.0 = "0." <> BigInt.toString n
| abs (BigInt.toNumber n) < 10.0 = (if n < zero then "-" else "") <> "0.0" <> BigInt.toString n
| abs (BigInt.toNumber n) < 100.0 = (if n < zero then "-" else "") <> "0." <> BigInt.toString n
| otherwise = fromCharArray <<< snd $ foldr formatCentsToDollars' (Tuple 0 []) (chars n)
where
chars :: BigInt -> Array Char
Expand Down
16 changes: 16 additions & 0 deletions test/Test/Data/Currency.purs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import Prelude
import Ocelot.Data.Currency (Cents(..), formatCentsToStrDollars, parseCentsFromDollarStr, parseCentsFromMicroDollars)
import Data.BigInt as BigInt
import Data.Maybe (Maybe(..))
import Test.QuickCheck ((===))
import Test.Unit as Test.Unit
import Test.Unit.Assert as Test.Unit.Assert
import Test.Unit.QuickCheck as Test.Unit.QuickCheck

suite :: Test.Unit.TestSuite
suite = do
Expand Down Expand Up @@ -56,6 +58,11 @@ suite = do
result = parseCentsFromDollarStr "1,234."
Test.Unit.Assert.equal expect result

Test.Unit.test "parseCentsFromDollarStr -1,234.50" do
let expect = Just $ Cents $ BigInt.fromInt (-123450)
result = parseCentsFromDollarStr "-1,234.50"
Test.Unit.Assert.equal expect result

Test.Unit.test "formatCentsToStrDollars 0.00" do
let result = formatCentsToStrDollars $ Cents $ BigInt.fromInt 0
Test.Unit.Assert.equal "0.00" result
Expand All @@ -71,3 +78,12 @@ suite = do
Test.Unit.test "formatCentsToStrDollars 1,234.00" do
let result = formatCentsToStrDollars $ Cents $ BigInt.fromInt 123400
Test.Unit.Assert.equal "1,234.00" result

Test.Unit.test "formatCentsToStrDollars -1,234.50" do
let result = formatCentsToStrDollars $ Cents $ BigInt.fromInt (-123450)
Test.Unit.Assert.equal "-1,234.50" result

Test.Unit.test "Just cents === parseCentsFromDollarStr (formatCentsToStrDollars cents)" do
Test.Unit.QuickCheck.quickCheck \int -> do
let cents = Cents $ BigInt.fromInt int
Just cents === parseCentsFromDollarStr (formatCentsToStrDollars cents)

0 comments on commit e8e271c

Please sign in to comment.