Skip to content

Commit e8e271c

Browse files
Merge pull request #227 from citizennet/arthur/negative-cents
Fix `Ocelot.Data.Currency` functions not working with negative `Cents` values
2 parents 0a4af1d + d38be6a commit e8e271c

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "purescript-ocelot",
3-
"version": "0.33.1",
3+
"version": "0.33.2",
44
"private": true,
55
"scripts": {
66
"build-all": "make build",

src/Data/Currency.purs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Data.Foldable (foldr)
1414
import Data.Int (fromString) as Int
1515
import Data.Maybe (Maybe(..), fromMaybe, isJust)
1616
import Data.Newtype (class Newtype, unwrap)
17+
import Data.Ord (abs)
1718
import Data.String (Pattern(..), Replacement(..), length, replaceAll, split, take, null)
1819
import Data.String.CodeUnits (toCharArray, fromCharArray)
1920
import Data.Tuple (Tuple(..), snd)
@@ -81,9 +82,11 @@ parseCentsFromDollarStr str = Cents <$> case split (Pattern ".") str of
8182

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

8891
-- Unable to parse
8992
_ -> Nothing
@@ -115,8 +118,8 @@ parseCentsFromDollarStr str = Cents <$> case split (Pattern ".") str of
115118
-- in dollars.
116119
formatCentsToStrDollars :: Cents -> String
117120
formatCentsToStrDollars (Cents n)
118-
| BigInt.toNumber n < 10.0 = "0.0" <> BigInt.toString n
119-
| BigInt.toNumber n < 100.0 = "0." <> BigInt.toString n
121+
| abs (BigInt.toNumber n) < 10.0 = (if n < zero then "-" else "") <> "0.0" <> BigInt.toString n
122+
| abs (BigInt.toNumber n) < 100.0 = (if n < zero then "-" else "") <> "0." <> BigInt.toString n
120123
| otherwise = fromCharArray <<< snd $ foldr formatCentsToDollars' (Tuple 0 []) (chars n)
121124
where
122125
chars :: BigInt -> Array Char

test/Test/Data/Currency.purs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import Prelude
55
import Ocelot.Data.Currency (Cents(..), formatCentsToStrDollars, parseCentsFromDollarStr, parseCentsFromMicroDollars)
66
import Data.BigInt as BigInt
77
import Data.Maybe (Maybe(..))
8+
import Test.QuickCheck ((===))
89
import Test.Unit as Test.Unit
910
import Test.Unit.Assert as Test.Unit.Assert
11+
import Test.Unit.QuickCheck as Test.Unit.QuickCheck
1012

1113
suite :: Test.Unit.TestSuite
1214
suite = do
@@ -56,6 +58,11 @@ suite = do
5658
result = parseCentsFromDollarStr "1,234."
5759
Test.Unit.Assert.equal expect result
5860

61+
Test.Unit.test "parseCentsFromDollarStr -1,234.50" do
62+
let expect = Just $ Cents $ BigInt.fromInt (-123450)
63+
result = parseCentsFromDollarStr "-1,234.50"
64+
Test.Unit.Assert.equal expect result
65+
5966
Test.Unit.test "formatCentsToStrDollars 0.00" do
6067
let result = formatCentsToStrDollars $ Cents $ BigInt.fromInt 0
6168
Test.Unit.Assert.equal "0.00" result
@@ -71,3 +78,12 @@ suite = do
7178
Test.Unit.test "formatCentsToStrDollars 1,234.00" do
7279
let result = formatCentsToStrDollars $ Cents $ BigInt.fromInt 123400
7380
Test.Unit.Assert.equal "1,234.00" result
81+
82+
Test.Unit.test "formatCentsToStrDollars -1,234.50" do
83+
let result = formatCentsToStrDollars $ Cents $ BigInt.fromInt (-123450)
84+
Test.Unit.Assert.equal "-1,234.50" result
85+
86+
Test.Unit.test "Just cents === parseCentsFromDollarStr (formatCentsToStrDollars cents)" do
87+
Test.Unit.QuickCheck.quickCheck \int -> do
88+
let cents = Cents $ BigInt.fromInt int
89+
Just cents === parseCentsFromDollarStr (formatCentsToStrDollars cents)

0 commit comments

Comments
 (0)