Skip to content

Commit

Permalink
Merge pull request #9 from crystal-money/develop
Browse files Browse the repository at this point in the history
v1.1
  • Loading branch information
Sija authored Apr 11, 2020
2 parents 64686f3 + b37392c commit 37384d2
Show file tree
Hide file tree
Showing 17 changed files with 97 additions and 92 deletions.
16 changes: 16 additions & 0 deletions .ameba.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This configuration file was generated by `ameba --gen-config`
# on 2020-02-16 01:09:31 UTC using Ameba version 0.11.0.
# The point is for the user to remove these configuration records
# one by one as the reported problems are removed from the code base.

# Problems found: 8
# Run `ameba --only Lint/ShadowingOuterLocalVar` for details
Lint/ShadowingOuterLocalVar:
Description: Disallows the usage of the same name as outer local variables for block
or proc arguments.
Enabled: true
Severity: Warning
Excluded:
- spec/bank/variable_exchange_spec.cr
- spec/money/exchange_spec.cr
- spec/money/arithmetic_spec.cr
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ install:

script:
- crystal spec
- crystal tool format --check src spec
- bin/ameba src
- crystal tool format --check
- bin/ameba
1 change: 1 addition & 0 deletions data/currencies/uzs.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"name": "Uzbekistan Som",
"symbol": "so'm",
"alternate_symbols": [
"so‘m",
"сўм",
"сум",
"s",
Expand Down
6 changes: 3 additions & 3 deletions shard.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name: money
version: 1.0.1
version: 1.1.0

authors:
- Sijawusz Pur Rahnama <sija@sija.pl>

development_dependencies:
ameba:
github: crystal-ameba/ameba
version: ~> 0.11.0
version: ~> 0.12.0

crystal: 0.30.1
crystal: 0.34.0

license: MIT
10 changes: 10 additions & 0 deletions src/ext/big_decimal.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# https://github.com/crystal-lang/crystal/issues/7856
struct BigDecimal
def to_json(json : JSON::Builder)
json.string(self)
end

def to_json_object_key
to_s
end
end
13 changes: 0 additions & 13 deletions src/money.cr
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
require "big"

# See https://github.com/crystal-lang/crystal/issues/8789
{% if compare_versions(Crystal::VERSION, "0.34.0") < 0 %}
struct BigDecimal
def in_scale(new_scale : UInt64) : BigDecimal
previous_def
end

def ceil : BigDecimal
previous_def.in_scale(0)
end
end
{% end %}

struct Money
end

Expand Down
2 changes: 1 addition & 1 deletion src/money/bank/variable_exchange.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ struct Money
def exchange(from : Money, to : Currency) : Money
rate = store[from.currency, to]
fractional = calculate_fractional(from, to)
fractional = fractional * rate
fractional *= rate
Money.new(fractional.to_big_i, to, self)
end

Expand Down
48 changes: 23 additions & 25 deletions src/money/currency.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ struct Money
# List of known currencies.
class_getter table : Hash(String, Currency) { load_currencies }

getter priority : Int32?
getter iso_numeric : UInt32?
getter code : String
getter name : String?
getter symbol : String?
getter alternate_symbols : Array(String)?
getter subunit : String?
getter subunit_to_unit : UInt64
getter? symbol_first : Bool?
getter html_entity : String?
getter decimal_mark : String?
getter thousands_separator : String?
getter smallest_denomination : UInt32?

# Currency ID, for time being lower-cased `#code`.
getter id : String { code.downcase }

def_equals_and_hash id

def self.register(currency : Currency)
table[currency.id] = currency
end
Expand Down Expand Up @@ -45,30 +64,11 @@ struct Money
end
end

# ditto
# :ditto:
def self.wrap(value : String | Symbol | Currency | Nil) : Currency
wrap?(value) || raise UnknownCurrencyError.new("Can't find currency: #{value}")
end

getter priority : Int32?
getter iso_numeric : UInt32?
getter code : String
getter name : String?
getter symbol : String?
getter alternate_symbols : Array(String)?
getter subunit : String?
getter subunit_to_unit : UInt64
getter? symbol_first : Bool?
getter html_entity : String?
getter decimal_mark : String?
getter thousands_separator : String?
getter smallest_denomination : UInt32?

# Currency ID, for time being lower-cased `#code`.
getter id : String { code.downcase }

def_equals_and_hash id

# Returns the relation between subunit and unit as a base 10 exponent.
#
# NOTE: MGA and MRU are exceptions and are rounded to 1.
Expand Down Expand Up @@ -98,10 +98,8 @@ struct Money
comparison = priority <=> other_priority
return id <=> other.id if comparison == 0
comparison
when {nil, Int32}
1
when {Int32, nil}
-1
when {Int32, nil} then -1
when {nil, Int32} then 1
else
id <=> other.id
end
Expand All @@ -119,7 +117,7 @@ struct Money
# Money::Currency.find(:usd).to_s # => "USD"
# Money::Currency.find(:eur).to_s # => "EUR"
# ```
def to_s(io)
def to_s(io : IO) : Nil
io << code
end
end
Expand Down
4 changes: 2 additions & 2 deletions src/money/currency/enumeration.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct Money
table[key.to_s.downcase]?
end

# ditto
# :ditto:
def []?(key : String | Symbol) : Currency?
find?(key)
end
Expand All @@ -30,7 +30,7 @@ struct Money
table[key.to_s.downcase]? || raise UnknownCurrencyError.new("Can't find currency: #{key}")
end

# ditto
# :ditto:
def [](key : String | Symbol) : Currency
find(key)
end
Expand Down
2 changes: 1 addition & 1 deletion src/money/currency/rate.cr
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Money::Currency
Money.new(@value, @to, bank)
end

def to_s(io)
def to_s(io : IO) : Nil
io << @from << " -> " << @to << ": " << to_big_d
end
end
Expand Down
2 changes: 1 addition & 1 deletion src/money/currency/rate_store.cr
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Money::Currency
transaction { get_rate?(from, to).try(&.to_big_d) }
end

# ditto
# :ditto:
def [](from, to) : BigDecimal
from, to = Currency.wrap(from), Currency.wrap(to)
self[from, to]? || raise UnknownRateError.new("No conversion rate known for #{from} -> #{to}")
Expand Down
34 changes: 17 additions & 17 deletions src/money/money.cr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct Money
# Sets the default currency for creating new `Money` object.
class_property default_currency : Currency { Currency.find("USD") }

# ditto
# :ditto:
def self.default_currency=(currency_code : String | Symbol)
self.default_currency = Currency.find(currency_code)
end
Expand Down Expand Up @@ -56,47 +56,47 @@ struct Money
end

# Creates a new `Money` object of value given as an *amount*
# of the given *currency*.
# of the given *currency* (as fractional if `Int`, or whole amount otherwise)
#
# ```
# Money.new # => Money(@amount=0 @currency="USD")
# Money.new(1.5) # => Money(@amount=1.5 @currency="USD")
# Money.new(1_50) # => Money(@amount=1.5 @currency="USD")
# Money.new(1.5, :usd) # => Money(@amount=1.5 @currency="USD")
# Money.new(1.5.to_big_d, "USD") # => Money(@amount=1.5 @currency="USD")
# Money.new(3.to_big_r, "EUR") # => Money(@amount=3 @currency="EUR")
# ```
def initialize(amount : Number = 0, currency = Money.default_currency)
initialize(amount, currency, nil)
def initialize(amount : Number = 0, currency = Money.default_currency, bank = nil)
initialize(amount, currency, bank)
end

# :ditto:
# :nodoc:
def initialize(amount : BigDecimal | BigRational, currency, bank)
@currency = Currency.wrap(currency)
@amount = amount.to_big_d
@bank = bank
end

# :ditto:
# :nodoc:
def initialize(amount : Float, currency, bank)
unless amount.finite?
raise ArgumentError.new "Must be initialized with a finite value"
end
initialize(amount.to_big_d, currency)
end

# Creates a new `Money` object of value given in the
# *fractional* unit of the given *currency*.
#
# ```
# Money.new(100) # => Money(@amount=1 @currency="USD")
# Money.new(100, "USD") # => Money(@amount=1 @currency="USD")
# Money.new(100, "EUR") # => Money(@amount=1 @currency="EUR")
# ```
# :nodoc:
def initialize(fractional : Int, currency, bank)
@currency = Currency.wrap(currency)
@amount = fractional.to_big_d / @currency.subunit_to_unit
@bank = bank
end

# Returns a new `Money` instance with same `currency` and `bank`
# properties set as in `self`.
protected def copy_with(**options) : Money
options = {currency: currency, bank: bank}.merge(options)
Money.new(**options)
end

# Returns hash value based on the `amount` and `currency` attributes.
def_hash amount, currency

Expand Down Expand Up @@ -163,6 +163,6 @@ struct Money

# See `#nearest_cash_value`.
def rounded_to_nearest_cash_value : Money
Money.new(nearest_cash_value, currency, bank)
copy_with(fractional: nearest_cash_value)
end
end
8 changes: 4 additions & 4 deletions src/money/money/allocate.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ struct Money
def split(num : Int) : Array(Money)
raise ArgumentError.new("Need at least one party") if num < 1

low = Money.new(fractional // num, currency, bank)
high = Money.new(low.fractional + 1, currency, bank)
low = copy_with(fractional: fractional // num)
high = copy_with(fractional: low.fractional + 1)

remainder = fractional % num

Expand Down Expand Up @@ -47,11 +47,11 @@ struct Money
amounts[i % size] += delta
end
amounts.map do |fractional|
Money.new(fractional.to_big_i, currency, bank)
copy_with(fractional: fractional.to_big_i)
end
end

# ditto
# :ditto:
def allocate(*splits : Number) : Array(Money)
allocate(splits)
end
Expand Down
Loading

0 comments on commit 37384d2

Please sign in to comment.