Empact-money 2.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +9 -0
- data/History.txt +0 -0
- data/MIT-LICENSE +21 -0
- data/Manifest.txt +24 -0
- data/README.rdoc +132 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/lib/money.rb +25 -0
- data/lib/money/acts_as_money.rb +41 -0
- data/lib/money/core_extensions.rb +139 -0
- data/lib/money/errors.rb +4 -0
- data/lib/money/exchange_bank.rb +116 -0
- data/lib/money/money.rb +344 -0
- data/money.gemspec +64 -0
- data/rails/init.rb +3 -0
- data/spec/db/database.yml +4 -0
- data/spec/db/schema.rb +14 -0
- data/spec/money/acts_as_money_spec.rb +95 -0
- data/spec/money/core_extensions_spec.rb +61 -0
- data/spec/money/exchange_bank_spec.rb +141 -0
- data/spec/money/money_spec.rb +277 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +20 -0
- data/tmp/.gitignore +0 -0
- metadata +81 -0
data/money.gemspec
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{money}
|
5
|
+
s.version = "2.3.6"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Money Team"]
|
9
|
+
s.date = %q{2009-05-29}
|
10
|
+
s.description = %q{This library aids one in handling money and different currencies.}
|
11
|
+
s.email = %q{see@reame}
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"README.rdoc"
|
14
|
+
]
|
15
|
+
s.files = [
|
16
|
+
".gitignore",
|
17
|
+
"History.txt",
|
18
|
+
"MIT-LICENSE",
|
19
|
+
"Manifest.txt",
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"lib/money.rb",
|
24
|
+
"lib/money/acts_as_money.rb",
|
25
|
+
"lib/money/core_extensions.rb",
|
26
|
+
"lib/money/errors.rb",
|
27
|
+
"lib/money/exchange_bank.rb",
|
28
|
+
"lib/money/money.rb",
|
29
|
+
"money.gemspec",
|
30
|
+
"rails/init.rb",
|
31
|
+
"spec/db/database.yml",
|
32
|
+
"spec/db/schema.rb",
|
33
|
+
"spec/money/acts_as_money_spec.rb",
|
34
|
+
"spec/money/core_extensions_spec.rb",
|
35
|
+
"spec/money/exchange_bank_spec.rb",
|
36
|
+
"spec/money/money_spec.rb",
|
37
|
+
"spec/spec.opts",
|
38
|
+
"spec/spec_helper.rb",
|
39
|
+
"tmp/.gitignore"
|
40
|
+
]
|
41
|
+
s.homepage = %q{http://github.com/nofxx/money}
|
42
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
43
|
+
s.require_paths = ["lib"]
|
44
|
+
s.rubygems_version = %q{1.3.3}
|
45
|
+
s.summary = %q{This library aids one in handling money and different currencies.}
|
46
|
+
s.test_files = [
|
47
|
+
"spec/money/exchange_bank_spec.rb",
|
48
|
+
"spec/money/acts_as_money_spec.rb",
|
49
|
+
"spec/money/money_spec.rb",
|
50
|
+
"spec/money/core_extensions_spec.rb",
|
51
|
+
"spec/db/schema.rb",
|
52
|
+
"spec/spec_helper.rb"
|
53
|
+
]
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
57
|
+
s.specification_version = 3
|
58
|
+
|
59
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
60
|
+
else
|
61
|
+
end
|
62
|
+
else
|
63
|
+
end
|
64
|
+
end
|
data/rails/init.rb
ADDED
data/spec/db/schema.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
ActiveRecord::Schema.define() do
|
2
|
+
|
3
|
+
create_table :accounts, :force => true do |t|
|
4
|
+
t.integer :value_cents, :total_cents
|
5
|
+
t.string :value_currency, :total_currency
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :products, :force => true do |t|
|
9
|
+
t.integer :value_cents, :tax_pennys
|
10
|
+
t.string :value_currency
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../../rails/init.rb'
|
3
|
+
|
4
|
+
class Account < ActiveRecord::Base
|
5
|
+
has_money :value, :total, :allow_nil => true
|
6
|
+
end
|
7
|
+
|
8
|
+
class Product < ActiveRecord::Base
|
9
|
+
has_money :value, :allow_nil => false
|
10
|
+
has_money :tax, :cents => "pennys", :with_currency => false
|
11
|
+
|
12
|
+
validates_numericality_of :value_cents, :greater_than => 0
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Acts as Money" do
|
16
|
+
|
17
|
+
|
18
|
+
it "should accept nil" do
|
19
|
+
@account = Account.create(:value => nil)
|
20
|
+
@account.should be_valid
|
21
|
+
@account.value.should be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should require money" do
|
25
|
+
@product = Product.create(:value => nil)
|
26
|
+
@product.should have(1).errors
|
27
|
+
@product.value.should == Money.new(0)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should require money" do
|
31
|
+
@product_fake = Product.create(:value => nil)
|
32
|
+
@product_fake.value_cents.should eql(0)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should create" do
|
36
|
+
@account = Account.create!(:value => 10, :total => "20 BRL")
|
37
|
+
@account.should be_valid
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should write to the db" do
|
41
|
+
lambda do
|
42
|
+
@account = Account.create!(:value => 10, :total => "20 BRL")
|
43
|
+
end.should change(Account, :count).by(1)
|
44
|
+
Account.last.total.format.should eql("R$20,00")
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
describe "Account" do
|
50
|
+
|
51
|
+
before(:each) do
|
52
|
+
@account = Account.create!(:value => 10, :total => "20 BRL")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return an instance of Money" do
|
56
|
+
@account.value.should be_instance_of(Money)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should format out nicely" do
|
60
|
+
@account.value.format.should eql("$10.00")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should include nicely" do
|
64
|
+
@account.value.to_s.should eql("10.00")
|
65
|
+
@account.total.to_s.should eql("20.00")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should map cents" do
|
69
|
+
@account.value_cents.to_s.should eql("1000")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should map currency" do
|
73
|
+
@account.value_currency.should eql("USD")
|
74
|
+
@account.total_currency.should eql("BRL")
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "Product" do
|
80
|
+
|
81
|
+
before(:each) do
|
82
|
+
@product = Product.create(:value => 10, :tax => 2)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should map attributes" do
|
86
|
+
@product.pennys.should eql(200)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should map currency on tax" do
|
90
|
+
@product.should_not respond_to(:tax_currency)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe "Money core extensions" do
|
4
|
+
describe "Numberic#to_money works" do
|
5
|
+
it "should convert integer to money" do
|
6
|
+
money = 1234.to_money
|
7
|
+
money.cents.should == 1234_00
|
8
|
+
money.currency.should == Money.default_currency
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should convert float to money" do
|
12
|
+
money = 100.37.to_money
|
13
|
+
money.cents.should == 100_37
|
14
|
+
money.currency.should == Money.default_currency
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "String#to_money" do
|
19
|
+
EXAMPLES = {
|
20
|
+
"20.15" => {:cents => Money.new(20_15), :no_cents => Money.new(20_15)},
|
21
|
+
"100" => {:cents => Money.new(100_00), :no_cents => Money.new(100)},
|
22
|
+
"100.37" => {:cents => Money.new(100_37), :no_cents => Money.new(100_37)},
|
23
|
+
"100,37" => {:cents => Money.new(100_37), :no_cents => Money.new(100_37)},
|
24
|
+
"100 000" => {:cents => Money.new(100_000_00), :no_cents => Money.new(100_000)},
|
25
|
+
"100.000,45" => {:cents => Money.new(100_000_45), :no_cents => Money.new(100_000_45)},
|
26
|
+
"-100.100,45" => {:cents => Money.new(-100_100_45), :no_cents => Money.new(-100_100_45)},
|
27
|
+
|
28
|
+
"100 USD" => {:cents => Money.new(100_00, "USD"), :no_cents => Money.new(100, "USD")},
|
29
|
+
"-100 USD" => {:cents => Money.new(-100_00, "USD"), :no_cents => Money.new(-100, "USD")},
|
30
|
+
"100 EUR" => {:cents => Money.new(100_00, "EUR"), :no_cents => Money.new(100, "EUR")},
|
31
|
+
"100.37 EUR" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100_37, "EUR")},
|
32
|
+
"100,37 EUR" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100_37, "EUR")},
|
33
|
+
|
34
|
+
"USD 100" => {:cents => Money.new(100_00, "USD"), :no_cents => Money.new(100, "USD")},
|
35
|
+
"EUR 100" => {:cents => Money.new(100_00, "EUR"), :no_cents => Money.new(100, "EUR")},
|
36
|
+
"EUR 100.37" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100_37, "EUR")},
|
37
|
+
"CAD -100.37" => {:cents => Money.new(-100_37, "CAD"), :no_cents => Money.new(-100_37, "CAD")},
|
38
|
+
"EUR 100,37" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100_37, "EUR")},
|
39
|
+
"EUR -100,37" => {:cents => Money.new(-100_37, "EUR"), :no_cents => Money.new(-100_37, "EUR")},
|
40
|
+
|
41
|
+
"BRL 100,37" => {:cents => Money.new(100_37, "BRL"), :no_cents => Money.new(100_37, "BRL")},
|
42
|
+
"BRL -100,37" => {:cents => Money.new(-100_37, "BRL"), :no_cents => Money.new(-100_37, "BRL")},
|
43
|
+
|
44
|
+
"$100 USD" => {:cents => Money.new(100_00, "USD"), :no_cents => Money.new(100, "USD")}
|
45
|
+
}
|
46
|
+
|
47
|
+
EXAMPLES.each_pair do |string, expected_money|
|
48
|
+
it "should convert '#{string}' with cents by default" do
|
49
|
+
string.to_money.should == expected_money[:cents]
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should convert '#{string}' without cents" do
|
53
|
+
string.to_money(true).should == expected_money[:no_cents]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should convert '#{string}' with cents" do
|
57
|
+
string.to_money(false).should == expected_money[:cents]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe Money::ExchangeBank do
|
4
|
+
before :each do
|
5
|
+
@bank = Money::ExchangeBank.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "returns the previously specified conversion rate" do
|
9
|
+
@bank.add_rate("USD", "EUR", 0.788332676)
|
10
|
+
@bank.add_rate("EUR", "YEN", 122.631477)
|
11
|
+
@bank.get_rate("USD", "EUR").should == 0.788332676
|
12
|
+
@bank.get_rate("EUR", "YEN").should == 122.631477
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns the previously specified conversion rate" do
|
16
|
+
@bank.add_rate("USD", "EUR", 0.788332676)
|
17
|
+
@bank.add_rate("EUR", "YEN", 122.631477)
|
18
|
+
@bank.get_rate("USD", "EUR").should == 0.788332676
|
19
|
+
@bank.get_rate("EUR", "YEN").should == 122.631477
|
20
|
+
end
|
21
|
+
|
22
|
+
it "treats currency names case-insensitively" do
|
23
|
+
@bank.add_rate("usd", "eur", 1)
|
24
|
+
@bank.get_rate("USD", "EUR").should == 1
|
25
|
+
@bank.same_currency?("USD", "usd").should be_true
|
26
|
+
@bank.same_currency?("EUR", "usd").should be_false
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns nil if the conversion rate is unknown" do
|
30
|
+
@bank.get_rate("American Pesos", "EUR").should be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "exchanges money from one currency to another according to the specified conversion rates" do
|
34
|
+
@bank.add_rate("USD", "EUR", 0.5)
|
35
|
+
@bank.add_rate("EUR", "YEN", 10)
|
36
|
+
@bank.exchange(10_00, "USD", "EUR").should == 5_00
|
37
|
+
@bank.exchange(500_00, "EUR", "YEN").should == 5000_00
|
38
|
+
end
|
39
|
+
|
40
|
+
it "rounds the exchanged result down" do
|
41
|
+
@bank.add_rate("USD", "EUR", 0.788332676)
|
42
|
+
@bank.add_rate("EUR", "YEN", 122.631477)
|
43
|
+
@bank.exchange(10_00, "USD", "EUR").should == 7_88
|
44
|
+
@bank.exchange(500_00, "EUR", "YEN").should == 6131573
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns the previously specified conversion rate" do
|
48
|
+
@bank.add_rate("EUR", 122.631477)
|
49
|
+
@bank.get_rate("EUR").should == 122.631477
|
50
|
+
end
|
51
|
+
|
52
|
+
it "treats currency names case-insensitively" do
|
53
|
+
@bank.add_rate("yen", 1)
|
54
|
+
@bank.get_rate("YEN").should == 1
|
55
|
+
@bank.same_currency?("USD", "usd").should be_true
|
56
|
+
@bank.same_currency?("EUR", "usd").should be_false
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should work with a different default currency" do
|
60
|
+
Money.default_currency = "BRL"
|
61
|
+
@bank.add_rate("yen", 10)
|
62
|
+
@bank.exchange(5_00, "brl", "yen").should == 50_00
|
63
|
+
Money.default_currency = "USD"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns nil if the conversion rate is unknown" do
|
67
|
+
@bank.get_rate("American Pesos").should be_nil
|
68
|
+
end
|
69
|
+
|
70
|
+
it "exchanges money from one currency to another according to the specified conversion rates" do
|
71
|
+
@bank.add_rate("EUR", 0.5)
|
72
|
+
@bank.add_rate("YEN", 5)
|
73
|
+
@bank.exchange(10_00, "USD", "EUR").should == 5_00
|
74
|
+
@bank.exchange(500_00, "USD", "YEN").should == 2500_00
|
75
|
+
@bank.exchange(2500_00, "YEN", "USD").should == 500_00
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should deal fine with FOO_TO_FOO" do
|
79
|
+
@bank.add_rate("USD", 2.0)
|
80
|
+
@bank.get_rate("USD").should be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should test some more" do
|
84
|
+
@bank.add_rate("EUR", 0.788332676)
|
85
|
+
@bank.add_rate("YEN", 122.631477)
|
86
|
+
@bank.exchange(10_00, "USD", "EUR").should == 788
|
87
|
+
@bank.exchange(500_00, "USD", "YEN").should == 6131573
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raises Money::UnknownRate upon conversion if the conversion rate is unknown" do
|
91
|
+
block = lambda { @bank.exchange(10, "USD", "ABC") }
|
92
|
+
block.should raise_error(Money::UnknownRate)
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "Fetching Data" do
|
96
|
+
|
97
|
+
before(:each) do
|
98
|
+
URI.should_receive(:parse).with("http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml").and_return(:uri)
|
99
|
+
Net::HTTP.should_receive(:get).with(:uri).and_return("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gesmes:Envelope xmlns:gesmes=\"http://www.gesmes.org/xml/2002-08-01\" xmlns=\"http://www.ecb.int/vocabulary/2002-08-01/eurofxref\">\n\t<gesmes:subject>Reference rates</gesmes:subject>\n\t<gesmes:Sender>\n\t\t<gesmes:name>European Central Bank</gesmes:name>\n\t</gesmes:Sender>\n\t<Cube>\n\t\t<Cube time='2009-05-29'>\n\t\t\t<Cube currency='USD' rate='1.4098'/>\n\t\t\t<Cube currency='JPY' rate='135.22'/>\n\t\t\t<Cube currency='BGN' rate='1.9558'/>\n\t\t\t<Cube currency='CZK' rate='26.825'/>\n\t\t\t<Cube currency='DKK' rate='7.4453'/>\n\t\t\t<Cube currency='EEK' rate='15.6466'/>\n\t\t\t<Cube currency='GBP' rate='0.87290'/>\n\t\t\t<Cube currency='HUF' rate='282.48'/>\n\t\t\t<Cube currency='LTL' rate='3.4528'/>\n\t\t\t<Cube currency='LVL' rate='0.7093'/>\n\t\t\t<Cube currency='PLN' rate='4.4762'/>\n\t\t\t<Cube currency='RON' rate='4.1825'/>\n\t\t\t<Cube currency='SEK' rate='10.6678'/>\n\t\t\t<Cube currency='CHF' rate='1.5128'/>\n\t\t\t<Cube currency='NOK' rate='8.8785'/>\n\t\t\t<Cube currency='HRK' rate='7.3500'/>\n\t\t\t<Cube currency='RUB' rate='43.4455'/>\n\t\t\t<Cube currency='TRY' rate='2.1737'/>\n\t\t\t<Cube currency='AUD' rate='1.7671'/>\n\t\t\t<Cube currency='BRL' rate='2.8320'/>\n\t\t\t<Cube currency='CAD' rate='1.5501'/>\n\t\t\t<Cube currency='CNY' rate='9.6263'/>\n\t\t\t<Cube currency='HKD' rate='10.9273'/>\n\t\t\t<Cube currency='IDR' rate='14539.26'/>\n\t\t\t<Cube currency='INR' rate='66.4260'/>\n\t\t\t<Cube currency='KRW' rate='1764.04'/>\n\t\t\t<Cube currency='MXN' rate='18.4340'/>\n\t\t\t<Cube currency='MYR' rate='4.9167'/>\n\t\t\t<Cube currency='NZD' rate='2.2135'/>\n\t\t\t<Cube currency='PHP' rate='66.516'/>\n\t\t\t<Cube currency='SGD' rate='2.0350'/>\n\t\t\t<Cube currency='THB' rate='48.377'/>\n\t\t\t<Cube currency='ZAR' rate='11.2413'/>\n\t\t</Cube>\n\t</Cube>\n</gesmes:Envelope>")
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should fetch data" do
|
103
|
+
Money.stub!(:default_currency).and_return("EUR")
|
104
|
+
@bank.fetch_rates
|
105
|
+
@bank.get_rate("DKK").should be_close(7.4453, 0.0001)
|
106
|
+
@bank.get_rate("BRL").should be_close(2.832, 0.001)
|
107
|
+
@bank.exchange(10_00, "EUR", "DKK").should == 74_45
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should fetch diff than eur" do
|
111
|
+
Money.stub!(:default_currency).and_return("BRL")
|
112
|
+
@bank.fetch_rates
|
113
|
+
@bank.get_rate("DKK").should be_close(2.6289, 0.0001)
|
114
|
+
@bank.get_rate("EEK").should be_close(5.5249, 0.0001)
|
115
|
+
@bank.get_rate("EUR").should be_close(2.832, 0.001)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should fetch for an unknown one" do
|
119
|
+
Money.stub!(:default_currency).and_return("XXX")
|
120
|
+
@bank.fetch_rates
|
121
|
+
@bank.get_rate("DKK").should be_nil
|
122
|
+
@bank.get_rate("EUR", "USD").should be_close(1.4098, 0.001)
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "Live Fetching" do
|
128
|
+
|
129
|
+
if ENV["LIVE"]
|
130
|
+
|
131
|
+
it "should fetch data live" do
|
132
|
+
@bank.fetch_rates
|
133
|
+
@bank.get_rate("DKK").should_not be_nil
|
134
|
+
@bank.get_rate("EUR").should_not be_nil
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,277 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
3
|
+
|
4
|
+
describe Money do
|
5
|
+
|
6
|
+
it { Money.new(10_00).to_f.should eql(10.0) }
|
7
|
+
it { Money.new(10_00).to_s.should eql("10.00") }
|
8
|
+
it { Money.new(199).to_i.should eql(199) }
|
9
|
+
|
10
|
+
it "is associated to the singleton instance of ExchangeBank by default" do
|
11
|
+
Money.new(0).bank.object_id.should == Money::ExchangeBank.instance.object_id
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return the amount of cents passed to the constructor" do
|
15
|
+
Money.new(200_00, "USD").cents.should == 200_00
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should rounds the given cents to an integer" do
|
19
|
+
Money.new(1.0, "USD").cents.should == 1
|
20
|
+
Money.new(1.01, "USD").cents.should == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should use the floor method" do
|
24
|
+
Money.new(1.50, "USD").cents.should == 1
|
25
|
+
Money.new(1.99, "USD").cents.should == 1
|
26
|
+
end
|
27
|
+
|
28
|
+
it "#currency returns the currency passed to the constructor" do
|
29
|
+
Money.new(200_00, "USD").currency.should == "USD"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "#zero? returns whether the amount is 0" do
|
33
|
+
Money.new(0, "USD").should be_zero
|
34
|
+
Money.new(0, "EUR").should be_zero
|
35
|
+
Money.new(1, "USD").should_not be_zero
|
36
|
+
Money.new(10, "YEN").should_not be_zero
|
37
|
+
Money.new(-1, "EUR").should_not be_zero
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should exchange_to exchanges the amount via its exchange bank" do
|
41
|
+
money = Money.new(100_00, "USD")
|
42
|
+
money.bank.should_receive(:exchange).with(100_00, "USD", "EUR").and_return(200_00)
|
43
|
+
money.exchange_to("EUR")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should exchange_to exchanges the amount properly" do
|
47
|
+
money = Money.new(100_00, "USD")
|
48
|
+
money.bank.should_receive(:exchange).with(100_00, "USD", "EUR").and_return(200_00)
|
49
|
+
money.exchange_to("EUR").should == Money.new(200_00, "EUR")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should returns true if and only if their amount and currency are equal" do
|
53
|
+
Money.new(1_00, "USD").should == Money.new(1_00, "USD")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should add retaining the currency" do
|
57
|
+
(Money.new(1_00, "USD") + 10).should == Money.new(1_10, "USD")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should substract retaining the currency" do
|
61
|
+
(Money.new(1_00, "USD") - 10).should == Money.new(90, "USD")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should multiply while retaining the currency" do
|
65
|
+
(Money.new(1_00, "USD") * 10).should == Money.new(10_00, "USD")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should divides while retaining the currency" do
|
69
|
+
(Money.new(10_00, "USD") / 10).should == Money.new(1_00, "USD")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should create a new Money object of 0 cents if empty" do
|
73
|
+
Money.empty.should == Money.new(0)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "Money.ca_dollar creates a new Money object of the given value in CAD" do
|
77
|
+
Money.ca_dollar(50).should == Money.new(50, "CAD")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "Money.us_dollar creates a new Money object of the given value in USD" do
|
81
|
+
Money.us_dollar(50).should == Money.new(50, "USD")
|
82
|
+
end
|
83
|
+
|
84
|
+
it "Money.euro creates a new Money object of the given value in EUR" do
|
85
|
+
Money.euro(50).should == Money.new(50, "EUR")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "Money.real creates a new Money object of the given value in BRL" do
|
89
|
+
Money.real(50).should == Money.new(50, "BRL")
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "Installments" do
|
93
|
+
|
94
|
+
it "# divides the money ammout in installments add first" do
|
95
|
+
@money = Money.new(10_00).split_in_installments(3)
|
96
|
+
@money[0].cents.should eql(334)
|
97
|
+
@money[1].cents.should eql(333)
|
98
|
+
@money[2].cents.should eql(333)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "# divides the money ammout in installments add last" do
|
102
|
+
@money = Money.new(10_00).split_in_installments(3,true)
|
103
|
+
@money.to_s.should eql(["3.33", "3.33", "3.34"])
|
104
|
+
end
|
105
|
+
|
106
|
+
it "# divides the money ammout in installments base on payment" do
|
107
|
+
money = Money.new(3_00)
|
108
|
+
Money.new(10_00).in_installments_of(money)[0].cents.should eql(334)
|
109
|
+
Money.new(10_00).in_installments_of(money)[1].cents.should eql(333)
|
110
|
+
Money.new(10_00).in_installments_of(money)[2].cents.should eql(333)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "shuld sum array" do
|
114
|
+
Money.new(10_00).split_in_installments(3).sum.cents.should eql(1000)
|
115
|
+
Money.new(19_99).split_in_installments(3).sum.cents.should eql(1999)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should calculate tax" do
|
119
|
+
Money.new(100).add_tax(20).cents.should eql(120)
|
120
|
+
Money.new(100).add_tax(-20).cents.should eql(80)
|
121
|
+
Money.new(1218).add_tax(19).cents.should eql(1449)
|
122
|
+
Money.new(1218).add_tax(-19).cents.should eql(987)
|
123
|
+
Money.new(1000).add_tax(150).cents.should eql(2500)
|
124
|
+
Money.new(1000).add_tax(-150).cents.should eql(-500)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should round to .50 coin" do
|
128
|
+
Money.new(14_58).round_to_coin(50).cents.should eql(1450)
|
129
|
+
Money.new(14_58).round_to_coin(10).cents.should eql(1450)
|
130
|
+
Money.new(14_58).round_to_coin(5).cents.should eql(1455)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should provide tax breakdown" do
|
134
|
+
Money.new(1225).tax_breakdown(19).map{|c| c.to_s}.should eql(['14.58','2.33'])
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should provide reverse tax breakdown" do
|
138
|
+
Money.new(-8).tax_reverse_breakdown(19).map{|c| c.to_s}.should eql(['-0.07','-0.01'])
|
139
|
+
end
|
140
|
+
|
141
|
+
it "shuld to_s wallet" do
|
142
|
+
@money = Money.new(10_00)
|
143
|
+
@money.split_in_installments(3).to_s.should eql(["3.34", "3.33", "3.33"])
|
144
|
+
end
|
145
|
+
|
146
|
+
it "shuld sum array" do
|
147
|
+
@money = Money.new(10_00).add_tax(10)
|
148
|
+
@money.split_in_installments(3).sum.cents.should eql(1100)
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "Taxes and Interest" do
|
154
|
+
|
155
|
+
it "Money rate works" do
|
156
|
+
Money.add_rate("EUR", "USD", 10)
|
157
|
+
Money.new(10_00, "EUR").exchange_to("USD").should == Money.new(100_00, "USD")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "Money.add_rate works" do
|
161
|
+
Money.add_rate("BGL", 10)
|
162
|
+
Money.new(10_00, "USD").exchange_to("BGL").should == Money.new(100_00, "BGL")
|
163
|
+
end
|
164
|
+
|
165
|
+
it "Money method missing exchange" do
|
166
|
+
Money.add_rate("EUR", "BRL", 10)
|
167
|
+
Money.new(10_00, "EUR").as_brl.should == Money.new(100_00, "BRL")
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should calculate compound tax" do
|
171
|
+
m = Money.new(1000_00)
|
172
|
+
m.compound_interest(12.99,12).to_s.should eql("137.91")
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should simple interest" do
|
176
|
+
m = Money.new(1000_00)
|
177
|
+
m.simple_interest(12.99,12).to_s.should eql("129.90")
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should calculate compound interest" do
|
181
|
+
m = Money.new(2500_00)
|
182
|
+
m.compound_interest(12.99,3).to_s.should eql("82.06")
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should calculate compound interest" do
|
186
|
+
m = Money.new(2500_00)
|
187
|
+
m.compound_interest(12.99,3,6).to_s.should eql("165.91")
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "Format out " do
|
193
|
+
|
194
|
+
describe "Options" do
|
195
|
+
before(:each) do
|
196
|
+
@cash = Money.new(2_00, "JPY")
|
197
|
+
end
|
198
|
+
|
199
|
+
it { @cash.format.should eql("¥2.00") }
|
200
|
+
it { @cash.format(:symbol => "R$ ").should eql("R$ 2.00") }
|
201
|
+
it { @cash.format(:no_cents => true).should eql("¥2") }
|
202
|
+
it { @cash.format(:no_cents => true, :symbol => "R$ ").should eql("R$ 2") }
|
203
|
+
it { @cash.format(:html => true).should eql("¥2.00") }
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
it { Money.new(0).format.should eql("$0.00") }
|
208
|
+
it { Money.new(0).format(:display_free => true).should eql("free") }
|
209
|
+
it { Money.new(0).format(:display_free => "GRATIS").should eql("GRATIS") }
|
210
|
+
|
211
|
+
it { Money.new(9).format.should eql("$0.09") }
|
212
|
+
it { Money.new(99).format.should eql("$0.99") }
|
213
|
+
it { Money.new(800).format.should eql("$8.00") }
|
214
|
+
it { Money.new(-8000).format(:no_cents => true).should eql("$-80") }
|
215
|
+
it { Money.new(80000).format.should eql("$800.00") }
|
216
|
+
it { Money.new(800000).format.should eql("$8,000.00") }
|
217
|
+
it { Money.new(-8000000, "JPY").format(:no_cents => true).should eql("¥-80.000") }
|
218
|
+
it { Money.new(87654321, "BRL").format.should eql("R$876.543,21") }
|
219
|
+
it { Money.new(87654321, "brl").format.should eql("R$876.543,21") }
|
220
|
+
it { Money.new(800000000, "BRL").format.should eql("R$8.000.000,00") }
|
221
|
+
it { Money.new(8000000000, "BRL").format.should eql("R$80.000.000,00") }
|
222
|
+
it { Money.new(80000000000, "CAD").format.should eql("$800,000,000.00") }
|
223
|
+
it { Money.new(880000000000, "GBP").format(:no_cents => true).should eql("£8,800,000,000") }
|
224
|
+
it { Money.new(8800000000088, "EUR").format.should eql("€88,000,000,000.88") }
|
225
|
+
|
226
|
+
it "should fail nicely if symbol can`t be found" do
|
227
|
+
Money.stub!(:default_currency).and_return("XXX")
|
228
|
+
Money.new(800).format.should eql("$8.00")
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "Actions involving two Money objects" do
|
232
|
+
describe "if the other Money object has the same currency" do
|
233
|
+
it "#<=> compares the two objects' amounts" do
|
234
|
+
(Money.new(1_00, "USD") <=> Money.new(1_00, "USD")).should == 0
|
235
|
+
(Money.new(1_00, "USD") <=> Money.new(99, "USD")).should > 0
|
236
|
+
(Money.new(1_00, "USD") <=> Money.new(2_00, "USD")).should < 0
|
237
|
+
end
|
238
|
+
|
239
|
+
it "#+ adds the other object's amount to the current object's amount while retaining the currency" do
|
240
|
+
(Money.new(10_00, "USD") + Money.new(90, "USD")).should == Money.new(10_90, "USD")
|
241
|
+
end
|
242
|
+
|
243
|
+
it "#- substracts the other object's amount from the current object's amount while retaining the currency" do
|
244
|
+
(Money.new(10_00, "USD") - Money.new(90, "USD")).should == Money.new(9_10, "USD")
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
describe "if the other Money object has a different currency" do
|
249
|
+
it "#<=> compares the two objects' amount after converting the other object's amount to its own currency" do
|
250
|
+
target = Money.new(200_00, "EUR")
|
251
|
+
target.should_receive(:exchange_to).with("USD").and_return(Money.new(300_00, "USD"))
|
252
|
+
(Money.new(100_00, "USD") <=> target).should < 0
|
253
|
+
|
254
|
+
target = Money.new(200_00, "EUR")
|
255
|
+
target.should_receive(:exchange_to).with("USD").and_return(Money.new(100_00, "USD"))
|
256
|
+
(Money.new(100_00, "USD") <=> target).should == 0
|
257
|
+
|
258
|
+
target = Money.new(200_00, "EUR")
|
259
|
+
target.should_receive(:exchange_to).with("USD").and_return(Money.new(99_00, "USD"))
|
260
|
+
(Money.new(100_00, "USD") <=> target).should > 0
|
261
|
+
end
|
262
|
+
|
263
|
+
it "#+ adds the other object's amount, converted to this object's currency, to this object's amount while retaining its currency" do
|
264
|
+
other = Money.new(90, "EUR")
|
265
|
+
other.should_receive(:exchange_to).with("USD").and_return(Money.new(9_00, "USD"))
|
266
|
+
(Money.new(10_00, "USD") + other).should == Money.new(19_00, "USD")
|
267
|
+
end
|
268
|
+
|
269
|
+
it "#- substracts the other object's amount, converted to this object's currency, from this object's amount while retaining its currency" do
|
270
|
+
other = Money.new(90, "EUR")
|
271
|
+
other.should_receive(:exchange_to).with("USD").and_return(Money.new(9_00, "USD"))
|
272
|
+
(Money.new(10_00, "USD") - other).should == Money.new(1_00, "USD")
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|