double_entry 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -1
  3. data/.rubocop.yml +55 -0
  4. data/.travis.yml +23 -12
  5. data/README.md +5 -1
  6. data/Rakefile +8 -3
  7. data/double_entry.gemspec +4 -3
  8. data/lib/active_record/locking_extensions.rb +28 -40
  9. data/lib/active_record/locking_extensions/log_subscriber.rb +4 -4
  10. data/lib/double_entry.rb +0 -2
  11. data/lib/double_entry/account.rb +13 -16
  12. data/lib/double_entry/account_balance.rb +0 -4
  13. data/lib/double_entry/balance_calculator.rb +4 -5
  14. data/lib/double_entry/configurable.rb +0 -2
  15. data/lib/double_entry/configuration.rb +2 -3
  16. data/lib/double_entry/errors.rb +2 -2
  17. data/lib/double_entry/line.rb +13 -16
  18. data/lib/double_entry/locking.rb +13 -18
  19. data/lib/double_entry/reporting.rb +2 -3
  20. data/lib/double_entry/reporting/aggregate.rb +90 -88
  21. data/lib/double_entry/reporting/aggregate_array.rb +58 -58
  22. data/lib/double_entry/reporting/day_range.rb +37 -35
  23. data/lib/double_entry/reporting/hour_range.rb +40 -37
  24. data/lib/double_entry/reporting/line_aggregate.rb +27 -28
  25. data/lib/double_entry/reporting/month_range.rb +67 -67
  26. data/lib/double_entry/reporting/time_range.rb +40 -38
  27. data/lib/double_entry/reporting/time_range_array.rb +3 -5
  28. data/lib/double_entry/reporting/week_range.rb +77 -78
  29. data/lib/double_entry/reporting/year_range.rb +27 -27
  30. data/lib/double_entry/transfer.rb +14 -15
  31. data/lib/double_entry/validation/line_check.rb +92 -86
  32. data/lib/double_entry/version.rb +1 -1
  33. data/lib/generators/double_entry/install/install_generator.rb +1 -2
  34. data/lib/generators/double_entry/install/templates/migration.rb +0 -2
  35. data/script/jack_hammer +1 -1
  36. data/spec/active_record/locking_extensions_spec.rb +45 -38
  37. data/spec/double_entry/account_balance_spec.rb +4 -5
  38. data/spec/double_entry/account_spec.rb +43 -44
  39. data/spec/double_entry/balance_calculator_spec.rb +6 -8
  40. data/spec/double_entry/configuration_spec.rb +14 -16
  41. data/spec/double_entry/line_spec.rb +25 -26
  42. data/spec/double_entry/locking_spec.rb +34 -39
  43. data/spec/double_entry/reporting/aggregate_array_spec.rb +8 -10
  44. data/spec/double_entry/reporting/aggregate_spec.rb +84 -44
  45. data/spec/double_entry/reporting/line_aggregate_spec.rb +7 -6
  46. data/spec/double_entry/reporting/month_range_spec.rb +109 -103
  47. data/spec/double_entry/reporting/time_range_array_spec.rb +145 -135
  48. data/spec/double_entry/reporting/time_range_spec.rb +36 -35
  49. data/spec/double_entry/reporting/week_range_spec.rb +82 -76
  50. data/spec/double_entry/reporting_spec.rb +9 -13
  51. data/spec/double_entry/transfer_spec.rb +13 -15
  52. data/spec/double_entry/validation/line_check_spec.rb +73 -79
  53. data/spec/double_entry_spec.rb +65 -68
  54. data/spec/generators/double_entry/install/install_generator_spec.rb +7 -10
  55. data/spec/spec_helper.rb +68 -10
  56. data/spec/support/accounts.rb +2 -4
  57. data/spec/support/double_entry_spec_helper.rb +4 -4
  58. data/spec/support/gemfiles/Gemfile.rails-3.2.x +1 -0
  59. metadata +31 -2
@@ -1,10 +1,8 @@
1
1
  # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- describe DoubleEntry::BalanceCalculator do
5
2
 
3
+ RSpec.describe DoubleEntry::BalanceCalculator do
6
4
  describe '#calculate' do
7
- let(:account) { DoubleEntry::account(:test, :scope => scope) }
5
+ let(:account) { DoubleEntry.account(:test, :scope => scope) }
8
6
  let(:scope) { User.make! }
9
7
  let(:from) { nil }
10
8
  let(:to) { nil }
@@ -42,7 +40,7 @@ describe DoubleEntry::BalanceCalculator do
42
40
 
43
41
  it 'ignores the time range when summing the lines' do
44
42
  expect(relation).to_not have_received(:where).with(
45
- :created_at => Time.parse('2014-06-19 10:09:18 +1000')..Time.parse('2014-06-19 20:09:18 +1000')
43
+ :created_at => Time.parse('2014-06-19 10:09:18 +1000')..Time.parse('2014-06-19 20:09:18 +1000'),
46
44
  )
47
45
  expect(relation).to_not have_received(:sum)
48
46
  end
@@ -55,7 +53,7 @@ describe DoubleEntry::BalanceCalculator do
55
53
 
56
54
  it 'scopes the lines summed to times within the given range' do
57
55
  expect(relation).to have_received(:where).with(
58
- :created_at => Time.parse('2014-06-19 10:09:18 +1000')..Time.parse('2014-06-19 20:09:18 +1000')
56
+ :created_at => Time.parse('2014-06-19 10:09:18 +1000')..Time.parse('2014-06-19 20:09:18 +1000'),
59
57
  )
60
58
  expect(relation).to have_received(:sum).with(:amount)
61
59
  end
@@ -72,10 +70,10 @@ describe DoubleEntry::BalanceCalculator do
72
70
  end
73
71
 
74
72
  context 'when a list of codes is provided' do
75
- let(:codes) { ['code1', 'code2'] }
73
+ let(:codes) { %w(code1 code2) }
76
74
 
77
75
  it 'scopes the lines summed by the given codes' do
78
- expect(relation).to have_received(:where).with(:code => ['code1', 'code2'])
76
+ expect(relation).to have_received(:where).with(:code => %w(code1 code2))
79
77
  expect(relation).to have_received(:sum).with(:amount)
80
78
  end
81
79
  end
@@ -1,28 +1,26 @@
1
1
  # encoding: utf-8
2
- require 'spec_helper'
3
- describe DoubleEntry::Configuration do
4
-
2
+ RSpec.describe DoubleEntry::Configuration do
5
3
  its(:accounts) { should be_a DoubleEntry::Account::Set }
6
4
  its(:transfers) { should be_a DoubleEntry::Transfer::Set }
7
5
 
8
- describe "max lengths" do
9
- context "given a max length has not been set" do
6
+ describe 'max lengths' do
7
+ context 'given a max length has not been set' do
10
8
  its(:code_max_length) { should be 47 }
11
9
  its(:scope_identifier_max_length) { should be 23 }
12
10
  its(:account_identifier_max_length) { should be 31 }
13
11
  end
14
12
 
15
- context "given a code max length of 10 has been set" do
13
+ context 'given a code max length of 10 has been set' do
16
14
  before { subject.code_max_length = 10 }
17
15
  its(:code_max_length) { should be 10 }
18
16
  end
19
17
 
20
- context "given a scope identifier max length of 11 has been set" do
18
+ context 'given a scope identifier max length of 11 has been set' do
21
19
  before { subject.scope_identifier_max_length = 11 }
22
20
  its(:scope_identifier_max_length) { should be 11 }
23
21
  end
24
22
 
25
- context "given an account identifier max length of 9 has been set" do
23
+ context 'given an account identifier max length of 9 has been set' do
26
24
  before { subject.account_identifier_max_length = 9 }
27
25
  its(:account_identifier_max_length) { should be 9 }
28
26
  end
@@ -34,19 +32,19 @@ describe DoubleEntry::Configuration do
34
32
  end
35
33
  end
36
34
 
37
- describe "#define_accounts" do
38
- it "yields the accounts set" do
39
- expect { |block|
35
+ describe '#define_accounts' do
36
+ it 'yields the accounts set' do
37
+ expect do |block|
40
38
  subject.define_accounts(&block)
41
- }.to yield_with_args(be_a DoubleEntry::Account::Set)
39
+ end.to yield_with_args(be_a DoubleEntry::Account::Set)
42
40
  end
43
41
  end
44
42
 
45
- describe "#define_transfers" do
46
- it "yields the transfers set" do
47
- expect { |block|
43
+ describe '#define_transfers' do
44
+ it 'yields the transfers set' do
45
+ expect do |block|
48
46
  subject.define_transfers(&block)
49
- }.to yield_with_args(be_a DoubleEntry::Transfer::Set)
47
+ end.to yield_with_args(be_a DoubleEntry::Transfer::Set)
50
48
  end
51
49
  end
52
50
  end
@@ -1,12 +1,11 @@
1
1
  # encoding: utf-8
2
- require "spec_helper"
3
- describe DoubleEntry::Line do
4
- it "has a table name prefixed with double_entry_" do
5
- expect(DoubleEntry::Line.table_name).to eq "double_entry_lines"
2
+ RSpec.describe DoubleEntry::Line do
3
+ it 'has a table name prefixed with double_entry_' do
4
+ expect(DoubleEntry::Line.table_name).to eq 'double_entry_lines'
6
5
  end
7
6
 
8
- describe "persistance" do
9
- let(:line_to_persist) {
7
+ describe 'persistance' do
8
+ let(:line_to_persist) do
10
9
  DoubleEntry::Line.new(
11
10
  :amount => Money.new(10_00),
12
11
  :balance => Money.zero,
@@ -14,9 +13,9 @@ describe DoubleEntry::Line do
14
13
  :partner_account => partner_account,
15
14
  :code => code,
16
15
  )
17
- }
18
- let(:account) { DoubleEntry.account(:test, :scope => "17") }
19
- let(:partner_account) { DoubleEntry.account(:test, :scope => "72") }
16
+ end
17
+ let(:account) { DoubleEntry.account(:test, :scope => '17') }
18
+ let(:partner_account) { DoubleEntry.account(:test, :scope => '72') }
20
19
  let(:code) { :test_code }
21
20
 
22
21
  subject(:persisted_line) do
@@ -24,33 +23,33 @@ describe DoubleEntry::Line do
24
23
  line_to_persist.reload
25
24
  end
26
25
 
27
- describe "attributes" do
28
- context "given code = :the_code" do
26
+ describe 'attributes' do
27
+ context 'given code = :the_code' do
29
28
  let(:code) { :the_code }
30
29
  its(:code) { should eq :the_code }
31
30
  end
32
31
 
33
- context "given code = nil" do
32
+ context 'given code = nil' do
34
33
  let(:code) { nil }
35
34
  specify { expect { line_to_persist.save! }.to raise_error }
36
35
  end
37
36
 
38
- context "given account = :test, 54 " do
39
- let(:account) { DoubleEntry.account(:test, :scope => "54") }
40
- its("account.account.identifier") { should eq :test }
41
- its("account.scope") { should eq "54" }
37
+ context 'given account = :test, 54 ' do
38
+ let(:account) { DoubleEntry.account(:test, :scope => '54') }
39
+ its('account.account.identifier') { should eq :test }
40
+ its('account.scope') { should eq '54' }
42
41
  end
43
42
 
44
- context "given partner_account = :test, 91 " do
45
- let(:partner_account) { DoubleEntry.account(:test, :scope => "91") }
46
- its("partner_account.account.identifier") { should eq :test }
47
- its("partner_account.scope") { should eq "91" }
43
+ context 'given partner_account = :test, 91 ' do
44
+ let(:partner_account) { DoubleEntry.account(:test, :scope => '91') }
45
+ its('partner_account.account.identifier') { should eq :test }
46
+ its('partner_account.scope') { should eq '91' }
48
47
  end
49
48
 
50
- context "currency" do
51
- let(:account) { DoubleEntry.account(:btc_test, :scope => "17") }
52
- let(:partner_account) { DoubleEntry.account(:btc_test, :scope => "72") }
53
- its(:currency) { should eq "BTC" }
49
+ context 'currency' do
50
+ let(:account) { DoubleEntry.account(:btc_test, :scope => '17') }
51
+ let(:partner_account) { DoubleEntry.account(:btc_test, :scope => '72') }
52
+ its(:currency) { should eq 'BTC' }
54
53
  end
55
54
  end
56
55
 
@@ -74,8 +73,8 @@ describe DoubleEntry::Line do
74
73
  end
75
74
  end
76
75
 
77
- it "has a table name prefixed with double_entry_" do
78
- expect(DoubleEntry::Line.table_name).to eq "double_entry_lines"
76
+ it 'has a table name prefixed with double_entry_' do
77
+ expect(DoubleEntry::Line.table_name).to eq 'double_entry_lines'
79
78
  end
80
79
  end
81
80
  end
@@ -1,8 +1,6 @@
1
1
  # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- describe DoubleEntry::Locking do
5
2
 
3
+ RSpec.describe DoubleEntry::Locking do
6
4
  before do
7
5
  @config_accounts = DoubleEntry.configuration.accounts
8
6
  @config_transfers = DoubleEntry.configuration.transfers
@@ -33,16 +31,16 @@ describe DoubleEntry::Locking do
33
31
  end
34
32
  end
35
33
 
36
- @account_a = DoubleEntry.account(:account_a, :scope => "1")
37
- @account_b = DoubleEntry.account(:account_b, :scope => "2")
38
- @account_c = DoubleEntry.account(:account_c, :scope => "3")
39
- @account_d = DoubleEntry.account(:account_d, :scope => "4")
34
+ @account_a = DoubleEntry.account(:account_a, :scope => '1')
35
+ @account_b = DoubleEntry.account(:account_b, :scope => '2')
36
+ @account_c = DoubleEntry.account(:account_c, :scope => '3')
37
+ @account_d = DoubleEntry.account(:account_d, :scope => '4')
40
38
  @account_e = DoubleEntry.account(:account_e)
41
39
  end
42
40
 
43
- it "creates missing account balance records" do
41
+ it 'creates missing account balance records' do
44
42
  expect do
45
- DoubleEntry::Locking.lock_accounts(@account_a) { }
43
+ DoubleEntry::Locking.lock_accounts(@account_a) {}
46
44
  end.to change(DoubleEntry::AccountBalance, :count).by(1)
47
45
 
48
46
  account_balance = DoubleEntry::AccountBalance.find_by_account(@account_a)
@@ -50,7 +48,7 @@ describe DoubleEntry::Locking do
50
48
  expect(account_balance.balance).to eq Money.new(0)
51
49
  end
52
50
 
53
- it "takes the balance for new account balance records from the lines table" do
51
+ it 'takes the balance for new account balance records from the lines table' do
54
52
  DoubleEntry::Line.create!(
55
53
  :account => @account_a,
56
54
  :partner_account => @account_b,
@@ -67,7 +65,7 @@ describe DoubleEntry::Locking do
67
65
  )
68
66
 
69
67
  expect do
70
- DoubleEntry::Locking.lock_accounts(@account_a) { }
68
+ DoubleEntry::Locking.lock_accounts(@account_a) {}
71
69
  end.to change(DoubleEntry::AccountBalance, :count).by(1)
72
70
 
73
71
  account_balance = DoubleEntry::AccountBalance.find_by_account(@account_a)
@@ -75,43 +73,43 @@ describe DoubleEntry::Locking do
75
73
  expect(account_balance.balance).to eq Money.new(10_00)
76
74
  end
77
75
 
78
- it "prohibits locking inside a regular transaction" do
79
- expect {
76
+ it 'prohibits locking inside a regular transaction' do
77
+ expect do
80
78
  DoubleEntry::AccountBalance.transaction do
81
79
  DoubleEntry::Locking.lock_accounts(@account_a, @account_b) do
82
80
  end
83
81
  end
84
- }.to raise_error(DoubleEntry::Locking::LockMustBeOutermostTransaction)
82
+ end.to raise_error(DoubleEntry::Locking::LockMustBeOutermostTransaction)
85
83
  end
86
84
 
87
- it "prohibits a transfer inside a regular transaction" do
88
- expect {
85
+ it 'prohibits a transfer inside a regular transaction' do
86
+ expect do
89
87
  DoubleEntry::AccountBalance.transaction do
90
88
  DoubleEntry.transfer(Money.new(10_00), :from => @account_a, :to => @account_b, :code => :test)
91
89
  end
92
- }.to raise_error(DoubleEntry::Locking::LockMustBeOutermostTransaction)
90
+ end.to raise_error(DoubleEntry::Locking::LockMustBeOutermostTransaction)
93
91
  end
94
92
 
95
93
  it "allows a transfer inside a lock if we've locked the transaction accounts" do
96
- expect {
94
+ expect do
97
95
  DoubleEntry::Locking.lock_accounts(@account_a, @account_b) do
98
96
  DoubleEntry.transfer(Money.new(10_00), :from => @account_a, :to => @account_b, :code => :test)
99
97
  end
100
- }.to_not raise_error
98
+ end.to_not raise_error
101
99
  end
102
100
 
103
101
  it "does not allow a transfer inside a lock if the right locks aren't held" do
104
- expect {
102
+ expect do
105
103
  DoubleEntry::Locking.lock_accounts(@account_a, @account_c) do
106
104
  DoubleEntry.transfer(Money.new(10_00), :from => @account_a, :to => @account_b, :code => :test)
107
105
  end
108
- }.to raise_error(DoubleEntry::Locking::LockNotHeld, "No lock held for account: account_b, scope 2")
106
+ end.to raise_error(DoubleEntry::Locking::LockNotHeld, 'No lock held for account: account_b, scope 2')
109
107
  end
110
108
 
111
- it "allows nested locks if the outer lock locks all the accounts" do
109
+ it 'allows nested locks if the outer lock locks all the accounts' do
112
110
  expect do
113
111
  DoubleEntry::Locking.lock_accounts(@account_a, @account_b) do
114
- DoubleEntry::Locking.lock_accounts(@account_a, @account_b) { }
112
+ DoubleEntry::Locking.lock_accounts(@account_a, @account_b) {}
115
113
  end
116
114
  end.to_not raise_error
117
115
  end
@@ -119,15 +117,15 @@ describe DoubleEntry::Locking do
119
117
  it "prohibits nested locks if the out lock doesn't lock all the accounts" do
120
118
  expect do
121
119
  DoubleEntry::Locking.lock_accounts(@account_a) do
122
- DoubleEntry::Locking.lock_accounts(@account_a, @account_b) { }
120
+ DoubleEntry::Locking.lock_accounts(@account_a, @account_b) {}
123
121
  end
124
- end.to raise_error(DoubleEntry::Locking::LockNotHeld, "No lock held for account: account_b, scope 2")
122
+ end.to raise_error(DoubleEntry::Locking::LockNotHeld, 'No lock held for account: account_b, scope 2')
125
123
  end
126
124
 
127
- it "rolls back a locking transaction" do
125
+ it 'rolls back a locking transaction' do
128
126
  DoubleEntry::Locking.lock_accounts(@account_a, @account_b) do
129
127
  DoubleEntry.transfer(Money.new(10_00), :from => @account_a, :to => @account_b, :code => :test)
130
- raise ActiveRecord::Rollback
128
+ fail ActiveRecord::Rollback
131
129
  end
132
130
  expect(DoubleEntry.balance(@account_a)).to eq Money.new(0)
133
131
  expect(DoubleEntry.balance(@account_b)).to eq Money.new(0)
@@ -137,27 +135,24 @@ describe DoubleEntry::Locking do
137
135
  expect do
138
136
  DoubleEntry::Locking.lock_accounts(@account_a, @account_b) do
139
137
  DoubleEntry.transfer(Money.new(10_00), :from => @account_a, :to => @account_b, :code => :test)
140
- raise "Yeah, right"
138
+ fail 'Yeah, right'
141
139
  end
142
- end.to raise_error("Yeah, right")
140
+ end.to raise_error('Yeah, right')
143
141
  expect(DoubleEntry.balance(@account_a)).to eq Money.new(0)
144
142
  expect(DoubleEntry.balance(@account_b)).to eq Money.new(0)
145
143
  end
146
144
 
147
- it "allows locking a scoped account and a non scoped account" do
145
+ it 'allows locking a scoped account and a non scoped account' do
148
146
  expect do
149
- DoubleEntry::Locking.lock_accounts(@account_d, @account_e) do
150
- # do nothing
151
- end
147
+ DoubleEntry::Locking.lock_accounts(@account_d, @account_e) {}
152
148
  end.to_not raise_error
153
149
  end
154
150
 
155
151
  # sqlite cannot handle these cases so they don't run when DB=sqlite
156
- describe "concurrent locking", :unless => ENV['DB'] == 'sqlite' do
157
-
158
- it "allows multiple threads to lock at the same time" do
152
+ describe 'concurrent locking', :unless => ENV['DB'] == 'sqlite' do
153
+ it 'allows multiple threads to lock at the same time' do
159
154
  expect do
160
- threads = Array.new
155
+ threads = []
161
156
 
162
157
  threads << Thread.new do
163
158
  sleep 0.05
@@ -177,8 +172,8 @@ describe DoubleEntry::Locking do
177
172
  end.to_not raise_error
178
173
  end
179
174
 
180
- it "allows multiple threads to lock accounts without balances at the same time" do
181
- threads = Array.new
175
+ it 'allows multiple threads to lock accounts without balances at the same time' do
176
+ threads = []
182
177
  expect do
183
178
  threads << Thread.new { DoubleEntry::Locking.lock_accounts(@account_a, @account_b) { sleep 0.1 } }
184
179
  threads << Thread.new { DoubleEntry::Locking.lock_accounts(@account_c, @account_d) { sleep 0.1 } }
@@ -1,8 +1,6 @@
1
- require 'spec_helper'
2
1
  module DoubleEntry
3
2
  module Reporting
4
- describe AggregateArray do
5
-
3
+ RSpec.describe AggregateArray do
6
4
  let(:user) { User.make! }
7
5
  let(:start) { nil }
8
6
  let(:finish) { nil }
@@ -10,7 +8,7 @@ module DoubleEntry
10
8
  let(:function) { :sum }
11
9
  let(:account) { :savings }
12
10
  let(:transfer_code) { :bonus }
13
- subject(:aggregate_array) {
11
+ subject(:aggregate_array) do
14
12
  Reporting.aggregate_array(
15
13
  function,
16
14
  account,
@@ -19,7 +17,7 @@ module DoubleEntry
19
17
  :start => start,
20
18
  :finish => finish,
21
19
  )
22
- }
20
+ end
23
21
 
24
22
  context 'given a deposit was made in 2007 and 2008' do
25
23
  before do
@@ -37,7 +35,7 @@ module DoubleEntry
37
35
  context 'when called with range type of "year"' do
38
36
  let(:range_type) { 'year' }
39
37
  let(:start) { '2006-08-03' }
40
- it { should eq [ Money.new(0), Money.new(10_00), Money.new(20_00), Money.new(0) ] }
38
+ it { should eq [Money.zero, Money.new(10_00), Money.new(20_00), Money.zero] }
41
39
  end
42
40
  end
43
41
  end
@@ -56,7 +54,7 @@ module DoubleEntry
56
54
  let(:range_type) { 'month' }
57
55
  let(:start) { '2006-09-01' }
58
56
  let(:finish) { '2007-01-02' }
59
- it { should eq [ Money.new(0), Money.new(10_00), Money.new(0), Money.new(20_00), Money.new(0), ] }
57
+ it { should eq [Money.zero, Money.new(10_00), Money.zero, Money.new(20_00), Money.zero] }
60
58
  end
61
59
 
62
60
  context 'given the date is 2007-02-02' do
@@ -65,7 +63,7 @@ module DoubleEntry
65
63
  context 'when called with range type of "month"' do
66
64
  let(:range_type) { 'month' }
67
65
  let(:start) { '2006-08-03' }
68
- it { should eq [ Money.new(0), Money.new(0), Money.new(10_00), Money.new(0), Money.new(20_00), Money.new(0), Money.new(0) ] }
66
+ it { should eq [Money.zero, Money.zero, Money.new(10_00), Money.zero, Money.new(20_00), Money.zero, Money.zero] }
69
67
  end
70
68
  end
71
69
  end
@@ -81,7 +79,7 @@ module DoubleEntry
81
79
  perform_btc_deposit(user, 100_000_000)
82
80
  end
83
81
 
84
- it { should eq [ Money.new(200_000_000, :btc) ] }
82
+ it { should eq [Money.new(200_000_000, :btc)] }
85
83
  end
86
84
 
87
85
  context 'when called with range type of "invalid_and_should_not_work"' do
@@ -96,7 +94,7 @@ module DoubleEntry
96
94
  let(:start) { '2006-08-03' }
97
95
  let(:function) { :invalid_function }
98
96
  it 'raises an AggregateFunctionNotSupported error' do
99
- expect{ aggregate_array }.to raise_error AggregateFunctionNotSupported
97
+ expect { aggregate_array }.to raise_error AggregateFunctionNotSupported
100
98
  end
101
99
  end
102
100
  end
@@ -1,9 +1,7 @@
1
1
  # encoding: utf-8
2
- require 'spec_helper'
3
2
  module DoubleEntry
4
3
  module Reporting
5
- describe Aggregate do
6
-
4
+ RSpec.describe Aggregate do
7
5
  let(:user) { User.make! }
8
6
  let(:expected_weekly_average) do
9
7
  (Money.new(20_00) + Money.new(40_00) + Money.new(50_00)) / 3
@@ -35,64 +33,84 @@ module DoubleEntry
35
33
  end
36
34
 
37
35
  it 'should store the aggregate for quick retrieval' do
38
- Reporting.aggregate(:sum, :savings, :bonus,
39
- :range => TimeRange.make(:year => 2009, :month => 10))
36
+ Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 10))
40
37
  expect(LineAggregate.count).to eq 1
41
38
  end
42
39
 
43
40
  it 'should only store the aggregate once if it is requested more than once' do
44
- Reporting.aggregate(:sum, :savings, :bonus,
45
- :range => TimeRange.make(:year => 2009, :month => 9))
46
- Reporting.aggregate(:sum, :savings, :bonus,
47
- :range => TimeRange.make(:year => 2009, :month => 9))
48
- Reporting.aggregate(:sum, :savings, :bonus,
49
- :range => TimeRange.make(:year => 2009, :month => 10))
41
+ Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 9))
42
+ Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 9))
43
+ Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 10))
50
44
  expect(LineAggregate.count).to eq 2
51
45
  end
52
46
 
53
47
  it 'should calculate the complete year correctly' do
54
48
  expect(
55
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009))
49
+ Reporting.aggregate(
50
+ :sum, :savings, :bonus,
51
+ :range => TimeRange.make(:year => 2009)
52
+ ),
56
53
  ).to eq Money.new(200_00)
57
54
  end
58
55
 
59
56
  it 'should calculate seperate months correctly' do
60
57
  expect(
61
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 10))
58
+ Reporting.aggregate(
59
+ :sum, :savings, :bonus,
60
+ :range => TimeRange.make(:year => 2009, :month => 10)
61
+ ),
62
62
  ).to eq Money.new(110_00)
63
63
  expect(
64
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 11))
64
+ Reporting.aggregate(
65
+ :sum, :savings, :bonus,
66
+ :range => TimeRange.make(:year => 2009, :month => 11)
67
+ ),
65
68
  ).to eq Money.new(90_00)
66
69
  end
67
70
 
68
71
  it 'should calculate seperate weeks correctly' do
69
72
  # Week 40 - Mon Sep 28, 2009 to Sun Oct 4 2009
70
73
  expect(
71
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 40))
74
+ Reporting.aggregate(
75
+ :sum, :savings, :bonus,
76
+ :range => TimeRange.make(:year => 2009, :week => 40)
77
+ ),
72
78
  ).to eq Money.new(60_00)
73
79
  end
74
80
 
75
81
  it 'should calculate seperate days correctly' do
76
82
  # 1 Nov 2009
77
83
  expect(
78
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 44, :day => 7))
84
+ Reporting.aggregate(
85
+ :sum, :savings, :bonus,
86
+ :range => TimeRange.make(:year => 2009, :week => 44, :day => 7)
87
+ ),
79
88
  ).to eq Money.new(90_00)
80
89
  end
81
90
 
82
91
  it 'should calculate seperate hours correctly' do
83
92
  # 1 Nov 2009
84
93
  expect(
85
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 44, :day => 7, :hour => 0))
94
+ Reporting.aggregate(
95
+ :sum, :savings, :bonus,
96
+ :range => TimeRange.make(:year => 2009, :week => 44, :day => 7, :hour => 0)
97
+ ),
86
98
  ).to eq Money.new(40_00)
87
99
  expect(
88
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 44, :day => 7, :hour => 1))
100
+ Reporting.aggregate(
101
+ :sum, :savings, :bonus,
102
+ :range => TimeRange.make(:year => 2009, :week => 44, :day => 7, :hour => 1)
103
+ ),
89
104
  ).to eq Money.new(50_00)
90
105
  end
91
106
 
92
107
  it 'should calculate, but not store aggregates when the time range is still current' do
93
108
  Timecop.freeze Time.local(2009, 11, 21) do
94
109
  expect(
95
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 11))
110
+ Reporting.aggregate(
111
+ :sum, :savings, :bonus,
112
+ :range => TimeRange.make(:year => 2009, :month => 11)
113
+ ),
96
114
  ).to eq Money.new(90_00)
97
115
  expect(LineAggregate.count).to eq 0
98
116
  end
@@ -101,7 +119,10 @@ module DoubleEntry
101
119
  it 'should calculate, but not store aggregates when the time range is in the future' do
102
120
  Timecop.freeze Time.local(2009, 11, 21) do
103
121
  expect(
104
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 12))
122
+ Reporting.aggregate(
123
+ :sum, :savings, :bonus,
124
+ :range => TimeRange.make(:year => 2009, :month => 12)
125
+ ),
105
126
  ).to eq Money.new(0)
106
127
  expect(LineAggregate.count).to eq 0
107
128
  end
@@ -109,51 +130,71 @@ module DoubleEntry
109
130
 
110
131
  it 'should calculate monthly all_time ranges correctly' do
111
132
  expect(
112
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 12, :range_type => :all_time))
133
+ Reporting.aggregate(
134
+ :sum, :savings, :bonus,
135
+ :range => TimeRange.make(:year => 2009, :month => 12, :range_type => :all_time)
136
+ ),
113
137
  ).to eq Money.new(200_00)
114
138
  end
115
139
 
116
140
  it 'calculates the average monthly all_time ranges correctly' do
117
141
  expect(
118
- Reporting.aggregate(:average, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 12, :range_type => :all_time))
142
+ Reporting.aggregate(
143
+ :average, :savings, :bonus,
144
+ :range => TimeRange.make(:year => 2009, :month => 12, :range_type => :all_time)
145
+ ),
119
146
  ).to eq expected_monthly_average
120
147
  end
121
148
 
122
149
  it 'returns the correct count for weekly all_time ranges correctly' do
123
150
  expect(
124
- Reporting.aggregate(:count, :savings, :bonus, :range => TimeRange.make(:year => 2009, :month => 12, :range_type => :all_time))
151
+ Reporting.aggregate(
152
+ :count, :savings, :bonus,
153
+ :range => TimeRange.make(:year => 2009, :month => 12, :range_type => :all_time)
154
+ ),
125
155
  ).to eq 5
126
156
  end
127
157
 
128
158
  it 'should calculate weekly all_time ranges correctly' do
129
159
  expect(
130
- Reporting.aggregate(:sum, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time))
160
+ Reporting.aggregate(
161
+ :sum, :savings, :bonus,
162
+ :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time)
163
+ ),
131
164
  ).to eq Money.new(110_00)
132
165
  end
133
166
 
134
167
  it 'calculates the average weekly all_time ranges correctly' do
135
168
  expect(
136
- Reporting.aggregate(:average, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time))
169
+ Reporting.aggregate(
170
+ :average, :savings, :bonus,
171
+ :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time)
172
+ ),
137
173
  ).to eq expected_weekly_average
138
174
  end
139
175
 
140
176
  it 'returns the correct count for weekly all_time ranges correctly' do
141
177
  expect(
142
- Reporting.aggregate(:count, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time))
178
+ Reporting.aggregate(
179
+ :count, :savings, :bonus,
180
+ :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time)
181
+ ),
143
182
  ).to eq 3
144
183
  end
145
184
 
146
- it "raises an AggregateFunctionNotSupported exception" do
147
- expect{
148
- Reporting.aggregate(:not_supported_calculation, :savings, :bonus, :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time))
149
- }.to raise_error(AggregateFunctionNotSupported)
185
+ it 'raises an AggregateFunctionNotSupported exception' do
186
+ expect do
187
+ Reporting.aggregate(
188
+ :not_supported_calculation, :savings, :bonus,
189
+ :range => TimeRange.make(:year => 2009, :week => 43, :range_type => :all_time)
190
+ )
191
+ end.to raise_error(AggregateFunctionNotSupported)
150
192
  end
151
193
 
152
194
  context 'filters' do
153
-
154
195
  let(:range) { TimeRange.make(:year => 2011, :month => 10) }
155
196
 
156
- class ::DoubleEntry::Line
197
+ DoubleEntry::Line.class_eval do
157
198
  scope :test_filter, -> { where(:amount => 10_00) }
158
199
  end
159
200
 
@@ -168,42 +209,41 @@ module DoubleEntry
168
209
  end
169
210
 
170
211
  it 'saves filtered aggregations' do
171
- expect {
212
+ expect do
172
213
  Reporting.aggregate(:sum, :savings, :bonus, :range => range, :filter => [:test_filter])
173
- }.to change { LineAggregate.count }.by 1
214
+ end.to change { LineAggregate.count }.by 1
174
215
  end
175
216
 
176
217
  it 'saves filtered aggregation only once for a range' do
177
- expect {
218
+ expect do
178
219
  Reporting.aggregate(:sum, :savings, :bonus, :range => range, :filter => [:test_filter])
179
220
  Reporting.aggregate(:sum, :savings, :bonus, :range => range, :filter => [:test_filter])
180
- }.to change { LineAggregate.count }.by 1
221
+ end.to change { LineAggregate.count }.by 1
181
222
  end
182
223
 
183
224
  it 'saves filtered aggregations and non filtered aggregations separately' do
184
- expect {
225
+ expect do
185
226
  Reporting.aggregate(:sum, :savings, :bonus, :range => range, :filter => [:test_filter])
186
227
  Reporting.aggregate(:sum, :savings, :bonus, :range => range)
187
- }.to change { LineAggregate.count }.by 2
228
+ end.to change { LineAggregate.count }.by 2
188
229
  end
189
230
 
190
231
  it 'loads the correct saved aggregation' do
191
-
192
232
  # cache the results for filtered and unfiltered aggregations
193
233
  Reporting.aggregate(:sum, :savings, :bonus, :range => range, :filter => [:test_filter])
194
234
  Reporting.aggregate(:sum, :savings, :bonus, :range => range)
195
235
 
196
236
  # ensure a second call loads the correct cached value
197
237
  expect(
198
- Reporting.aggregate(:sum, :savings, :bonus, :range => range, :filter => [:test_filter])
238
+ Reporting.aggregate(:sum, :savings, :bonus, :range => range, :filter => [:test_filter]),
199
239
  ).to eq Money.new(10_00)
200
240
  expect(
201
- Reporting.aggregate(:sum, :savings, :bonus, :range => range)
241
+ Reporting.aggregate(:sum, :savings, :bonus, :range => range),
202
242
  ).to eq Money.new(19_00)
203
243
  end
204
244
  end
205
245
  end
206
- describe Aggregate, "currencies" do
246
+ RSpec.describe Aggregate, 'currencies' do
207
247
  let(:user) { User.make! }
208
248
  before do
209
249
  perform_btc_deposit(user, 100_000_000)
@@ -212,8 +252,8 @@ module DoubleEntry
212
252
 
213
253
  it 'should calculate the sum in the correct currency' do
214
254
  expect(
215
- Reporting.aggregate(:sum, :btc_savings, :btc_test_transfer, :range => TimeRange.make(:year => Time.now.year))
216
- ).to eq Money.new(300_000_000, :btc)
255
+ Reporting.aggregate(:sum, :btc_savings, :btc_test_transfer, :range => TimeRange.make(:year => Time.now.year)),
256
+ ).to eq(Money.new(300_000_000, :btc))
217
257
  end
218
258
  end
219
259
  end