double_entry 1.0.1 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +432 -0
  3. data/README.md +36 -9
  4. data/double_entry.gemspec +20 -48
  5. data/lib/active_record/locking_extensions.rb +3 -3
  6. data/lib/active_record/locking_extensions/log_subscriber.rb +1 -1
  7. data/lib/double_entry/account.rb +38 -45
  8. data/lib/double_entry/account_balance.rb +18 -1
  9. data/lib/double_entry/errors.rb +13 -13
  10. data/lib/double_entry/line.rb +3 -2
  11. data/lib/double_entry/reporting.rb +26 -38
  12. data/lib/double_entry/reporting/aggregate.rb +43 -23
  13. data/lib/double_entry/reporting/aggregate_array.rb +16 -13
  14. data/lib/double_entry/reporting/line_aggregate.rb +3 -2
  15. data/lib/double_entry/reporting/line_aggregate_filter.rb +8 -10
  16. data/lib/double_entry/reporting/line_metadata_filter.rb +33 -0
  17. data/lib/double_entry/transfer.rb +33 -27
  18. data/lib/double_entry/validation.rb +1 -0
  19. data/lib/double_entry/validation/account_fixer.rb +36 -0
  20. data/lib/double_entry/validation/line_check.rb +22 -40
  21. data/lib/double_entry/version.rb +1 -1
  22. data/lib/generators/double_entry/install/install_generator.rb +7 -1
  23. data/lib/generators/double_entry/install/templates/migration.rb +27 -25
  24. metadata +33 -243
  25. data/.gitignore +0 -32
  26. data/.rspec +0 -2
  27. data/.travis.yml +0 -29
  28. data/.yardopts +0 -2
  29. data/Gemfile +0 -2
  30. data/Rakefile +0 -15
  31. data/script/jack_hammer +0 -210
  32. data/script/setup.sh +0 -8
  33. data/spec/active_record/locking_extensions_spec.rb +0 -110
  34. data/spec/double_entry/account_balance_spec.rb +0 -7
  35. data/spec/double_entry/account_spec.rb +0 -130
  36. data/spec/double_entry/balance_calculator_spec.rb +0 -88
  37. data/spec/double_entry/configuration_spec.rb +0 -50
  38. data/spec/double_entry/line_spec.rb +0 -80
  39. data/spec/double_entry/locking_spec.rb +0 -214
  40. data/spec/double_entry/performance/double_entry_performance_spec.rb +0 -32
  41. data/spec/double_entry/performance/reporting/aggregate_performance_spec.rb +0 -50
  42. data/spec/double_entry/reporting/aggregate_array_spec.rb +0 -123
  43. data/spec/double_entry/reporting/aggregate_spec.rb +0 -205
  44. data/spec/double_entry/reporting/line_aggregate_filter_spec.rb +0 -90
  45. data/spec/double_entry/reporting/line_aggregate_spec.rb +0 -39
  46. data/spec/double_entry/reporting/month_range_spec.rb +0 -139
  47. data/spec/double_entry/reporting/time_range_array_spec.rb +0 -169
  48. data/spec/double_entry/reporting/time_range_spec.rb +0 -45
  49. data/spec/double_entry/reporting/week_range_spec.rb +0 -103
  50. data/spec/double_entry/reporting_spec.rb +0 -181
  51. data/spec/double_entry/transfer_spec.rb +0 -93
  52. data/spec/double_entry/validation/line_check_spec.rb +0 -99
  53. data/spec/double_entry_spec.rb +0 -428
  54. data/spec/generators/double_entry/install/install_generator_spec.rb +0 -30
  55. data/spec/spec_helper.rb +0 -118
  56. data/spec/support/accounts.rb +0 -21
  57. data/spec/support/blueprints.rb +0 -43
  58. data/spec/support/database.example.yml +0 -21
  59. data/spec/support/database.travis.yml +0 -24
  60. data/spec/support/double_entry_spec_helper.rb +0 -27
  61. data/spec/support/gemfiles/Gemfile.rails-3.2.x +0 -8
  62. data/spec/support/gemfiles/Gemfile.rails-4.1.x +0 -6
  63. data/spec/support/gemfiles/Gemfile.rails-4.2.x +0 -5
  64. data/spec/support/gemfiles/Gemfile.rails-5.0.x +0 -5
  65. data/spec/support/performance_helper.rb +0 -26
  66. data/spec/support/reporting_configuration.rb +0 -6
  67. data/spec/support/schema.rb +0 -74
@@ -1,39 +0,0 @@
1
- # encoding: utf-8
2
- RSpec.describe DoubleEntry::Reporting::LineAggregate do
3
- describe '.table_name' do
4
- subject { DoubleEntry::Reporting::LineAggregate.table_name }
5
- it { should eq('double_entry_line_aggregates') }
6
- end
7
-
8
- describe '#aggregate' do
9
- let(:line_relation) { spy }
10
- let(:filter) do
11
- instance_double(DoubleEntry::Reporting::LineAggregateFilter, :filter => line_relation)
12
- end
13
-
14
- let(:function) { :sum }
15
- let(:account) { spy }
16
- let(:code) { spy }
17
- let(:named_scopes) { spy }
18
- let(:range) { spy }
19
-
20
- subject(:aggregate) do
21
- DoubleEntry::Reporting::LineAggregate.aggregate(function, account, code, range, named_scopes)
22
- end
23
-
24
- before do
25
- allow(DoubleEntry::Reporting::LineAggregateFilter).to receive(:new).and_return(filter)
26
- aggregate
27
- end
28
-
29
- it 'applies the specified filters' do
30
- expect(DoubleEntry::Reporting::LineAggregateFilter).to have_received(:new).
31
- with(account, code, range, named_scopes)
32
- expect(filter).to have_received(:filter)
33
- end
34
-
35
- it 'performs the aggregation on the filtered lines' do
36
- expect(line_relation).to have_received(:sum).with(:amount)
37
- end
38
- end
39
- end
@@ -1,139 +0,0 @@
1
- # encoding: utf-8
2
- module DoubleEntry
3
- module Reporting
4
- RSpec.describe MonthRange do
5
- describe '.from_time' do
6
- subject(:from_time) { MonthRange.from_time(given_time) }
7
-
8
- context 'given the Time 31st March 2012' do
9
- let(:given_time) { Time.new(2012, 3, 31) }
10
- its(:year) { should eq 2012 }
11
- its(:month) { should eq 3 }
12
- end
13
-
14
- context 'given the Date 31st March 2012' do
15
- let(:given_time) { Date.parse('2012-03-31') }
16
- its(:year) { should eq 2012 }
17
- its(:month) { should eq 3 }
18
- end
19
- end
20
-
21
- describe '.reportable_months' do
22
- subject(:reportable_months) { MonthRange.reportable_months }
23
-
24
- context 'The date is 1st March 1970' do
25
- before { Timecop.freeze(Time.new(1970, 3, 1)) }
26
-
27
- specify do
28
- should eq [
29
- MonthRange.new(:year => 1970, :month => 1),
30
- MonthRange.new(:year => 1970, :month => 2),
31
- MonthRange.new(:year => 1970, :month => 3),
32
- ]
33
- end
34
-
35
- context 'My business started on 5th Feb 1970' do
36
- before do
37
- DoubleEntry::Reporting.configure do |config|
38
- config.start_of_business = Time.new(1970, 2, 5)
39
- end
40
- end
41
-
42
- specify do
43
- should eq [
44
- MonthRange.new(:year => 1970, :month => 2),
45
- MonthRange.new(:year => 1970, :month => 3),
46
- ]
47
- end
48
- end
49
- end
50
-
51
- context 'The date is 1st Jan 1970' do
52
- before { Timecop.freeze(Time.new(1970, 1, 1)) }
53
-
54
- it { should eq [MonthRange.new(:year => 1970, :month => 1)] }
55
- end
56
- end
57
-
58
- describe '.beginning_of_financial_year' do
59
- let(:month_range) { MonthRange.new(:year => year, :month => month) }
60
- let(:year) { 2014 }
61
-
62
- context 'the first month of the financial year is July' do
63
- subject(:beginning_of_financial_year) { month_range.beginning_of_financial_year }
64
- context 'returns the current year if the month is after July' do
65
- let(:month) { 10 }
66
- it { should eq(MonthRange.new(:year => 2014, :month => 7)) }
67
- end
68
-
69
- context 'returns the previous year if the month is before July' do
70
- let(:month) { 3 }
71
- it { should eq(MonthRange.new(:year => 2013, :month => 7)) }
72
- end
73
- end
74
-
75
- context 'the first month of the financial year is January' do
76
- subject(:beginning_of_financial_year) { month_range.beginning_of_financial_year }
77
-
78
- before do
79
- DoubleEntry::Reporting.configure do |config|
80
- config.first_month_of_financial_year = 1
81
- end
82
- end
83
-
84
- context 'returns the current year if the month is after January' do
85
- let(:month) { 10 }
86
- it { should eq(MonthRange.new(:year => 2014, :month => 1)) }
87
- end
88
-
89
- context 'returns the current year if the month is January' do
90
- let(:month) { 1 }
91
- it { should eq(MonthRange.new(:year => 2014, :month => 1)) }
92
- end
93
- end
94
-
95
- context 'the first month of the financial year is December' do
96
- subject(:beginning_of_financial_year) { month_range.beginning_of_financial_year }
97
-
98
- before do
99
- DoubleEntry::Reporting.configure do |config|
100
- config.first_month_of_financial_year = 12
101
- end
102
- end
103
-
104
- context 'returns the previous year if the month is before December (in the same year)' do
105
- let(:month) { 11 }
106
- it { should eq(MonthRange.new(:year => 2013, :month => 12)) }
107
- end
108
-
109
- context 'returns the previous year if the month is after December (in the next year)' do
110
- let(:year) { 2015 }
111
- let(:month) { 1 }
112
- it { should eq(MonthRange.new(:year => 2014, :month => 12)) }
113
- end
114
-
115
- context 'returns the current year if the month is December' do
116
- let(:month) { 12 }
117
- it { should eq(MonthRange.new(:year => 2014, :month => 12)) }
118
- end
119
- end
120
-
121
- context 'Given a start time of 3rd Dec 1982' do
122
- subject(:reportable_months) { MonthRange.reportable_months(:from => Time.new(1982, 12, 3)) }
123
-
124
- context 'The date is 2nd Feb 1983' do
125
- before { Timecop.freeze(Time.new(1983, 2, 2)) }
126
-
127
- specify do
128
- should eq [
129
- MonthRange.new(:year => 1982, :month => 12),
130
- MonthRange.new(:year => 1983, :month => 1),
131
- MonthRange.new(:year => 1983, :month => 2),
132
- ]
133
- end
134
- end
135
- end
136
- end
137
- end
138
- end
139
- end
@@ -1,169 +0,0 @@
1
- module DoubleEntry
2
- module Reporting
3
- RSpec.describe TimeRangeArray do
4
- describe '.make' do
5
- subject(:time_range_array) { TimeRangeArray.make(range_type, start, finish) }
6
-
7
- context 'for "hour" range type' do
8
- let(:range_type) { 'hour' }
9
-
10
- context 'given start is "2007-05-03 15:00:00" and finish is "2007-05-03 18:00:00"' do
11
- let(:start) { '2007-05-03 15:00:00' }
12
- let(:finish) { '2007-05-03 18:00:00' }
13
- specify do
14
- should eq [
15
- HourRange.from_time(Time.new(2007, 5, 3, 15)),
16
- HourRange.from_time(Time.new(2007, 5, 3, 16)),
17
- HourRange.from_time(Time.new(2007, 5, 3, 17)),
18
- HourRange.from_time(Time.new(2007, 5, 3, 18)),
19
- ]
20
- end
21
- end
22
-
23
- context 'given start and finish are nil' do
24
- it 'should raise an error' do
25
- expect { TimeRangeArray.make(range_type, nil, nil) }.
26
- to raise_error 'Must specify start of range'
27
- end
28
- end
29
- end
30
-
31
- context 'for "day" range type' do
32
- let(:range_type) { 'day' }
33
-
34
- context 'given start is "2007-05-03" and finish is "2007-05-07"' do
35
- let(:start) { '2007-05-03' }
36
- let(:finish) { '2007-05-07' }
37
- specify do
38
- should eq [
39
- DayRange.from_time(Time.new(2007, 5, 3)),
40
- DayRange.from_time(Time.new(2007, 5, 4)),
41
- DayRange.from_time(Time.new(2007, 5, 5)),
42
- DayRange.from_time(Time.new(2007, 5, 6)),
43
- DayRange.from_time(Time.new(2007, 5, 7)),
44
- ]
45
- end
46
- end
47
-
48
- context 'given start and finish are nil' do
49
- it 'should raise an error' do
50
- expect { TimeRangeArray.make(range_type, nil, nil) }.
51
- to raise_error 'Must specify start of range'
52
- end
53
- end
54
- end
55
-
56
- context 'for "week" range type' do
57
- let(:range_type) { 'week' }
58
-
59
- context 'given start is "2007-05-03" and finish is "2007-05-24"' do
60
- let(:start) { '2007-05-03' }
61
- let(:finish) { '2007-05-24' }
62
- specify do
63
- should eq [
64
- WeekRange.from_time(Time.new(2007, 5, 3)),
65
- WeekRange.from_time(Time.new(2007, 5, 10)),
66
- WeekRange.from_time(Time.new(2007, 5, 17)),
67
- WeekRange.from_time(Time.new(2007, 5, 24)),
68
- ]
69
- end
70
- end
71
-
72
- context 'given start and finish are nil' do
73
- it 'should raise an error' do
74
- expect { TimeRangeArray.make(range_type, nil, nil) }.
75
- to raise_error 'Must specify start of range'
76
- end
77
- end
78
- end
79
-
80
- context 'for "month" range type' do
81
- let(:range_type) { 'month' }
82
-
83
- context 'given start is "2007-05-03" and finish is "2007-08-24"' do
84
- let(:start) { '2007-05-03' }
85
- let(:finish) { '2007-08-24' }
86
- specify do
87
- should eq [
88
- MonthRange.from_time(Time.new(2007, 5)),
89
- MonthRange.from_time(Time.new(2007, 6)),
90
- MonthRange.from_time(Time.new(2007, 7)),
91
- MonthRange.from_time(Time.new(2007, 8)),
92
- ]
93
- end
94
- end
95
-
96
- context 'given finish is nil' do
97
- let(:start) { '2006-08-03' }
98
- let(:finish) { nil }
99
-
100
- context 'and the date is "2007-04-13"' do
101
- before { Timecop.freeze(Time.new(2007, 4, 13)) }
102
-
103
- specify do
104
- should eq [
105
- MonthRange.from_time(Time.new(2006, 8)),
106
- MonthRange.from_time(Time.new(2006, 9)),
107
- MonthRange.from_time(Time.new(2006, 10)),
108
- MonthRange.from_time(Time.new(2006, 11)),
109
- MonthRange.from_time(Time.new(2006, 12)),
110
- MonthRange.from_time(Time.new(2007, 1)),
111
- MonthRange.from_time(Time.new(2007, 2)),
112
- MonthRange.from_time(Time.new(2007, 3)),
113
- MonthRange.from_time(Time.new(2007, 4)),
114
- ]
115
- end
116
- end
117
- end
118
- end
119
-
120
- context 'for "year" range type' do
121
- let(:range_type) { 'year' }
122
-
123
- context 'given the date is "2009-11-23"' do
124
- before { Timecop.freeze(Time.new(2009, 11, 23)) }
125
-
126
- context 'given start is "2007-05-03" and finish is "2008-08-24"' do
127
- let(:start) { '2007-05-03' }
128
- let(:finish) { '2008-08-24' }
129
-
130
- it 'takes notice of start and finish' do
131
- should eq [
132
- YearRange.from_time(Time.new(2007)),
133
- YearRange.from_time(Time.new(2008)),
134
- ]
135
- end
136
- end
137
-
138
- context 'given the start of business is "2006-07-10"' do
139
- before do
140
- allow(DoubleEntry::Reporting).
141
- to receive_message_chain('configuration.start_of_business').
142
- and_return(Time.new(2006, 7, 10))
143
- end
144
-
145
- context 'given start and finish are nil' do
146
- let(:start) { nil }
147
- let(:finish) { nil }
148
- specify do
149
- should eq [
150
- YearRange.from_time(Time.new(2006)),
151
- YearRange.from_time(Time.new(2007)),
152
- YearRange.from_time(Time.new(2008)),
153
- YearRange.from_time(Time.new(2009)),
154
- ]
155
- end
156
- end
157
- end
158
- end
159
- end
160
-
161
- context 'given an invalid range type "ueue"' do
162
- it 'should raise an error' do
163
- expect { TimeRangeArray.make('ueue') }.to raise_error ArgumentError
164
- end
165
- end
166
- end
167
- end
168
- end
169
- end
@@ -1,45 +0,0 @@
1
- # encoding: utf-8
2
- module DoubleEntry
3
- module Reporting
4
- RSpec.describe TimeRange do
5
- it 'should correctly calculate a month range' do
6
- ar = TimeRange.make(:year => 2009, :month => 10)
7
- expect(ar.start.to_s).to eq Time.mktime(2009, 10, 1, 0, 0, 0).to_s
8
- expect(ar.finish.to_s).to eq Time.mktime(2009, 10, 31, 23, 59, 59).to_s
9
- end
10
-
11
- it 'should correctly calculate the beginning of the financial year' do
12
- range = TimeRange.make(:year => 2009, :month => 6).beginning_of_financial_year
13
- expect(range.month).to eq 7
14
- expect(range.year).to eq 2008
15
- range = TimeRange.make(:year => 2009, :month => 7).beginning_of_financial_year
16
- expect(range.month).to eq 7
17
- expect(range.year).to eq 2009
18
- end
19
-
20
- it "should correctly calculate the current week range for New Year's Day" do
21
- Timecop.freeze Time.mktime(2009, 1, 1) do
22
- expect(WeekRange.current.week).to eq 1
23
- end
24
- end
25
-
26
- it 'should correctly calculate the current week range for the first Sunday in the year after New Years' do
27
- Timecop.freeze Time.mktime(2009, 1, 4) do
28
- expect(WeekRange.current.week).to eq 1
29
- end
30
- end
31
-
32
- it 'should correctly calculate the current week range for the first Monday in the year after New Years' do
33
- Timecop.freeze Time.mktime(2009, 1, 5) do
34
- expect(WeekRange.current.week).to eq 2
35
- end
36
- end
37
-
38
- it 'should correctly calculate the current week range for my birthday' do
39
- Timecop.freeze Time.mktime(2009, 3, 27) do
40
- expect(WeekRange.current.week).to eq 13
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,103 +0,0 @@
1
- # encoding: utf-8
2
- module DoubleEntry
3
- module Reporting
4
- RSpec.describe WeekRange do
5
- it 'should start week 1 of a year in the first week that has any day in the year' do
6
- range = WeekRange.new(:year => 2011, :week => 1)
7
- expect(range.start).to eq Time.parse('2010-12-27 00:00:00')
8
- end
9
-
10
- it 'should handle times in the last week of the year properly' do
11
- range = WeekRange.from_time(Time.parse('2010-12-29 11:30:00'))
12
- expect(range.year).to eq 2011
13
- expect(range.week).to eq 1
14
- expect(range.start).to eq Time.parse('2010-12-27 00:00:00')
15
- end
16
-
17
- it 'handles daylight savings time properly' do
18
- Time.use_zone('America/Los_Angeles') do
19
- time = Time.zone.parse('Mon, 10 Mar 2014')
20
- range = WeekRange.from_time time
21
- expect(range.start.day).to eq 10
22
- end
23
- end
24
-
25
- describe '::from_time' do
26
- subject(:from_time) { WeekRange.from_time(given_time) }
27
-
28
- context 'given the Time 31st March 2012' do
29
- let(:given_time) { Time.new(2012, 3, 31) }
30
- its(:year) { should eq 2012 }
31
- its(:week) { should eq 14 }
32
- end
33
-
34
- context 'given the Date 31st March 2012' do
35
- let(:given_time) { Date.parse('2012-03-31') }
36
- its(:year) { should eq 2012 }
37
- its(:week) { should eq 14 }
38
- end
39
- end
40
-
41
- describe '::reportable_weeks' do
42
- subject(:reportable_weeks) { WeekRange.reportable_weeks }
43
-
44
- context 'The date is 1st Feb 1970' do
45
- before { Timecop.freeze(Time.new(1970, 2, 1)) }
46
-
47
- specify do
48
- should eq [
49
- WeekRange.new(:year => 1970, :week => 1),
50
- WeekRange.new(:year => 1970, :week => 2),
51
- WeekRange.new(:year => 1970, :week => 3),
52
- WeekRange.new(:year => 1970, :week => 4),
53
- WeekRange.new(:year => 1970, :week => 5),
54
- ]
55
- end
56
-
57
- context 'My business started on 25th Jan 1970' do
58
- before do
59
- DoubleEntry::Reporting.configure do |config|
60
- config.start_of_business = Time.new(1970, 1, 25)
61
- end
62
- end
63
-
64
- specify do
65
- should eq [
66
- WeekRange.new(:year => 1970, :week => 4),
67
- WeekRange.new(:year => 1970, :week => 5),
68
- ]
69
- end
70
- end
71
- end
72
-
73
- context 'The date is 1st Jan 1970' do
74
- before { Timecop.freeze(Time.new(1970, 1, 1)) }
75
-
76
- it { should eq [WeekRange.new(:year => 1970, :week => 1)] }
77
- end
78
-
79
- context 'Given a start time of 3rd Dec 1982' do
80
- subject(:reportable_weeks) { WeekRange.reportable_weeks(:from => Time.new(1982, 12, 3)) }
81
-
82
- context 'The date is 12nd Jan 1983' do
83
- before { Timecop.freeze(Time.new(1983, 2, 2)) }
84
- specify do
85
- should eq [
86
- WeekRange.new(:year => 1982, :week => 49),
87
- WeekRange.new(:year => 1982, :week => 50),
88
- WeekRange.new(:year => 1982, :week => 51),
89
- WeekRange.new(:year => 1982, :week => 52),
90
- WeekRange.new(:year => 1983, :week => 1),
91
- WeekRange.new(:year => 1983, :week => 2),
92
- WeekRange.new(:year => 1983, :week => 3),
93
- WeekRange.new(:year => 1983, :week => 4),
94
- WeekRange.new(:year => 1983, :week => 5),
95
- WeekRange.new(:year => 1983, :week => 6),
96
- ]
97
- end
98
- end
99
- end
100
- end
101
- end
102
- end
103
- end