Empact-money 2.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|