Skip to content

Commit d1d1bfa

Browse files
authored
Merge pull request #13 from PagoPlus/feat/display-decimal-amount
[FEAT] Displays decimal amount
2 parents 210af16 + 7bd1fae commit d1d1bfa

File tree

7 files changed

+353
-80
lines changed

7 files changed

+353
-80
lines changed

README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,9 @@ Where result will be something like this:
152152
```elixir
153153
iex> %{
154154
...> postings: [
155-
...> %Numscriptex.Posting{
155+
...> %Numscriptex.Posting{
156156
...> amount: 100,
157+
...> decimal_amount: 1.0,
157158
...> asset: "USD/2",
158159
...> destination: "bar",
159160
...> source: "foo"
@@ -164,19 +165,25 @@ iex> %{
164165
...> account: "foo",
165166
...> asset: "EUR/2",
166167
...> final_balance: 300,
167-
...> initial_balance: 300
168+
...> initial_balance: 300,
169+
...> decimal_final_balance: 3.0,
170+
...> decimal_initial_balance: 3.0,
168171
...> },
169172
...> %Numscriptex.Balance{
170173
...> account: "foo",
171174
...> asset: "USD/2",
172175
...> final_balance: 400,
173-
...> initial_balance: 500
176+
...> initial_balance: 500,
177+
...> decimal_final_balance: 4.0,
178+
...> decimal_initial_balance: 5.0,
174179
...> },
175180
...> %Numscriptex.Balance{
176181
...> account: "bar",
177182
...> asset: "USD/2",
178183
...> final_balance: 100,
179-
...> initial_balance: 0
184+
...> initial_balance: 0,
185+
...> decimal_final_balance: 1.0,
186+
...> decimal_initial_balance: 0.0,
180187
...> }
181188
...> ],
182189
...> accountMeta: %{}

lib/numscriptex/balance.ex

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,34 @@ defmodule Numscriptex.Balance do
55
can see the results of all transactions.
66
"""
77

8+
alias Numscriptex.Utilities
9+
810
@derive JSON.Encoder
911
defstruct account: nil,
1012
asset: nil,
1113
final_balance: nil,
12-
initial_balance: nil
14+
decimal_final_balance: nil,
15+
initial_balance: nil,
16+
decimal_initial_balance: nil
1317

1418
@typedoc """
1519
Type that represents `Numscriptex.Balance` struct.
1620
1721
## Fields
1822
* `:account` the account name
1923
* `:asset` the asset were the transaction was made
20-
* `:final_balance` balance after the transactions
21-
* `:initial_balance` balance before the transactions
24+
* `:final_balance` balance after the transactions (integer)
25+
* `:decimal_final_balance` balance after the transactions, but as float
26+
* `:initial_balance` balance before the transactions (integer)
27+
* `:decimal_initial_balance` balance after the transactions, but as float
2228
"""
2329
@type t() :: %__MODULE__{
2430
account: bitstring(),
2531
asset: bitstring(),
26-
final_balance: non_neg_integer(),
27-
initial_balance: non_neg_integer()
32+
final_balance: integer(),
33+
decimal_final_balance: float(),
34+
initial_balance: integer(),
35+
decimal_initial_balance: float()
2836
}
2937

3038
@doc """
@@ -57,19 +65,25 @@ defmodule Numscriptex.Balance do
5765
account: "foo",
5866
asset: "EUR/2",
5967
final_balance: 300,
60-
initial_balance: 300
68+
decimal_final_balance: 3.0,
69+
initial_balance: 300,
70+
decimal_initial_balance: 3.0
6171
},
6272
%Numscriptex.Balance{
6373
account: "foo",
6474
asset: "USD/2",
6575
final_balance: 400,
66-
initial_balance: 500
76+
decimal_final_balance: 4.0,
77+
initial_balance: 500,
78+
decimal_initial_balance: 5.0
6779
},
6880
%Numscriptex.Balance{
6981
account: "bar",
7082
asset: "USD/2",
7183
final_balance: 100,
72-
initial_balance: 0
84+
decimal_final_balance: 1.0,
85+
initial_balance: 0,
86+
decimal_initial_balance: 0.0
7387
}
7488
]
7589
```
@@ -82,9 +96,8 @@ defmodule Numscriptex.Balance do
8296
|> handle_initial_balance(account_assets)
8397
|> handle_final_balance(postings)
8498
|> maybe_drop_balance()
85-
|> then(fn balances ->
86-
Enum.map(balances, &struct(__MODULE__, &1))
87-
end)
99+
|> put_decimal_values()
100+
|> Enum.map(&struct(__MODULE__, &1))
88101
end
89102

90103
defp build_balances(account_assets, postings) do
@@ -100,8 +113,10 @@ defmodule Numscriptex.Balance do
100113
%{
101114
account: account,
102115
asset: asset,
116+
final_balance: 0,
117+
decimal_final_balance: 0,
103118
initial_balance: 0,
104-
final_balance: 0
119+
decimal_initial_balance: 0
105120
}
106121
end)
107122
end)
@@ -113,14 +128,18 @@ defmodule Numscriptex.Balance do
113128
%{
114129
account: posting["source"],
115130
asset: posting["asset"],
131+
final_balance: 0,
132+
decimal_final_balance: 0,
116133
initial_balance: 0,
117-
final_balance: 0
134+
decimal_initial_balance: 0
118135
},
119136
%{
120137
account: posting["destination"],
121138
asset: posting["asset"],
139+
final_balance: 0,
140+
decimal_final_balance: 0,
122141
initial_balance: 0,
123-
final_balance: 0
142+
decimal_initial_balance: 0
124143
}
125144
]
126145
end)
@@ -177,4 +196,19 @@ defmodule Numscriptex.Balance do
177196
balance.initial_balance == 0 and balance.final_balance == 0
178197
end)
179198
end
199+
200+
defp put_decimal_values(balances) do
201+
Enum.map(balances, fn
202+
%{initial_balance: initial_balance, final_balance: final_balance} = balance ->
203+
decimal_places = Utilities.decimal_places_from_asset(balance.asset)
204+
decimal_initial_balance = Utilities.integer_to_decimal(initial_balance, decimal_places)
205+
decimal_final_balance = Utilities.integer_to_decimal(final_balance, decimal_places)
206+
207+
%{
208+
balance
209+
| decimal_initial_balance: decimal_initial_balance,
210+
decimal_final_balance: decimal_final_balance
211+
}
212+
end)
213+
end
180214
end

lib/numscriptex/posting.ex

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ defmodule Numscriptex.Posting do
33
`Numscriptex.Postings` represents a financial transaction made with [Numscript](https://docs.formance.com/numscript/)
44
"""
55

6+
alias Numscriptex.Utilities
7+
68
@derive JSON.Encoder
79
defstruct amount: nil,
10+
decimal_amount: nil,
811
asset: nil,
912
destination: nil,
1013
source: nil
@@ -17,21 +20,37 @@ defmodule Numscriptex.Posting do
1720
* `:asset` the asset were the transaction was made
1821
* `:destination` account whose the money will go to
1922
* `:amount` amount of money transferred (integer)
23+
* `:decimal_amount` amount of money transferred, but as float
2024
"""
2125
@type t() :: %__MODULE__{
2226
amount: pos_integer(),
27+
decimal_amount: float(),
2328
asset: bitstring(),
2429
destination: bitstring(),
2530
source: bitstring()
2631
}
2732

28-
@spec from_list(map()) :: list(__MODULE__.t())
33+
@spec from_list(list(map())) :: list(__MODULE__.t())
2934
def from_list(postings) do
3035
Enum.map(postings, &from_map/1)
3136
end
3237

33-
@spec from_list(map()) :: __MODULE__.t()
34-
def from_map(map) do
35-
struct(%__MODULE__{}, map)
38+
@spec from_map(map()) :: __MODULE__.t()
39+
def from_map(posting) do
40+
put_decimal_amount(posting)
41+
end
42+
43+
defp put_decimal_amount(posting) when not is_struct(posting) do
44+
posting
45+
|> Map.put(:decimal_amount, 0)
46+
|> then(fn elem -> struct(%__MODULE__{}, elem) end)
47+
|> put_decimal_amount()
48+
end
49+
50+
defp put_decimal_amount(posting) do
51+
decimal_places = Utilities.decimal_places_from_asset(posting.asset)
52+
decimal_amount = Utilities.integer_to_decimal(posting.amount, decimal_places)
53+
54+
%{posting | decimal_amount: decimal_amount}
3655
end
3756
end

lib/numscriptex/utilities.ex

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,64 @@ defmodule Numscriptex.Utilities do
4343

4444
defp keys_to_atom({key, value}),
4545
do: {String.to_existing_atom(key), value}
46+
47+
@doc """
48+
Converts an integer value to float
49+
50+
```elixir
51+
iex> Utilities.integer_to_decimal(1000, 2)
52+
10.0
53+
54+
iex> Utilities.integer_to_decimal(1000, 3)
55+
1.0
56+
57+
iex> Utilities.integer_to_decimal(1000, 4)
58+
0.1
59+
60+
iex> Utilities.integer_to_decimal(1000, 5)
61+
0.01
62+
```
63+
"""
64+
@spec integer_to_decimal(pos_integer(), pos_integer() | nil) :: float()
65+
def integer_to_decimal(amount, decimal_places \\ 2)
66+
67+
def integer_to_decimal(amount, nil), do: integer_to_decimal(amount)
68+
69+
def integer_to_decimal(amount, decimal_places) do
70+
divisor =
71+
10
72+
|> Integer.pow(decimal_places)
73+
|> trunc()
74+
75+
amount / divisor
76+
end
77+
78+
@doc """
79+
Gets the decimal places from an asset if has any (e.g. decimal places for "USD/2" would be 2).
80+
You can choose a default value (the second argument), but if you don't choose any the default will be 2.
81+
82+
```elixir
83+
iex> Utilities.decimal_places_from_asset("USD/2")
84+
2
85+
86+
iex> Utilities.decimal_places_from_asset("USD/4")
87+
4
88+
89+
iex> Utilities.decimal_places_from_asset("USD")
90+
2
91+
92+
iex> Utilities.decimal_places_from_asset("USD", 3)
93+
3
94+
```
95+
"""
96+
@spec decimal_places_from_asset(bitstring(), pos_integer()) :: pos_integer()
97+
def decimal_places_from_asset(asset, default \\ 2) do
98+
if String.length(asset) >= 5 do
99+
asset
100+
|> String.last()
101+
|> String.to_integer()
102+
else
103+
default
104+
end
105+
end
46106
end

test/numscriptex/balance_test.exs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,25 @@ defmodule Numscriptex.BalanceTest do
3838
account: "bar",
3939
asset: "USD/2",
4040
final_balance: 50,
41-
initial_balance: 0
41+
decimal_final_balance: 0.5,
42+
initial_balance: 0,
43+
decimal_initial_balance: 0.0
4244
},
4345
%Numscriptex.Balance{
4446
account: "baz",
4547
asset: "USD/2",
4648
final_balance: 49,
47-
initial_balance: 0
49+
decimal_final_balance: 0.49,
50+
initial_balance: 0,
51+
decimal_initial_balance: 0.0
4852
},
4953
%Numscriptex.Balance{
5054
account: "foo",
5155
asset: "USD/2",
5256
final_balance: 1,
53-
initial_balance: 100
57+
initial_balance: 100,
58+
decimal_final_balance: 0.01,
59+
decimal_initial_balance: 1.0
5460
}
5561
]
5662

test/numscriptex/posting_tests.exs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule Numscriptex.PostingTest do
66
doctest Numscriptex.Posting
77

88
describe "from_map/1" do
9-
setup_all do
9+
setup do
1010
postings = [
1111
%{
1212
amount: 100,
@@ -18,7 +18,7 @@ defmodule Numscriptex.PostingTest do
1818
amount: 100,
1919
asset: "USD/2",
2020
destination: "baz",
21-
source: "foo"
21+
source: "bar"
2222
}
2323
]
2424

@@ -31,12 +31,14 @@ defmodule Numscriptex.PostingTest do
3131
assert postings == [
3232
%Numscriptex.Posting{
3333
amount: 100,
34+
decimal_amount: 1.0,
3435
asset: "USD/2",
3536
destination: "bar",
3637
source: "foo"
3738
},
3839
%Numscriptex.Posting{
3940
amount: 100,
41+
decimal_amount: 1.0,
4042
asset: "USD/2",
4143
destination: "baz",
4244
source: "bar"
@@ -49,6 +51,7 @@ defmodule Numscriptex.PostingTest do
4951

5052
assert posting == %Numscriptex.Posting{
5153
amount: 100,
54+
decimal_amount: 1.0,
5255
asset: "USD/2",
5356
destination: "bar",
5457
source: "foo"

0 commit comments

Comments
 (0)