double_entry 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +16 -14
- data/lib/double_entry.rb +9 -62
- data/lib/double_entry/account.rb +5 -1
- data/lib/double_entry/configuration.rb +21 -0
- data/lib/double_entry/reporting.rb +51 -0
- data/lib/double_entry/{aggregate.rb → reporting/aggregate.rb} +9 -7
- data/lib/double_entry/{aggregate_array.rb → reporting/aggregate_array.rb} +3 -1
- data/lib/double_entry/{day_range.rb → reporting/day_range.rb} +2 -0
- data/lib/double_entry/{hour_range.rb → reporting/hour_range.rb} +2 -0
- data/lib/double_entry/{line_aggregate.rb → reporting/line_aggregate.rb} +4 -2
- data/lib/double_entry/{month_range.rb → reporting/month_range.rb} +4 -2
- data/lib/double_entry/{time_range.rb → reporting/time_range.rb} +7 -5
- data/lib/double_entry/{time_range_array.rb → reporting/time_range_array.rb} +2 -0
- data/lib/double_entry/{week_range.rb → reporting/week_range.rb} +3 -1
- data/lib/double_entry/{year_range.rb → reporting/year_range.rb} +4 -3
- data/lib/double_entry/transfer.rb +4 -0
- data/lib/double_entry/validation.rb +1 -0
- data/lib/double_entry/{line_check.rb → validation/line_check.rb} +2 -0
- data/lib/double_entry/version.rb +1 -1
- data/script/jack_hammer +21 -16
- data/spec/double_entry/account_spec.rb +9 -0
- data/spec/double_entry/configuration_spec.rb +23 -0
- data/spec/double_entry/locking_spec.rb +24 -13
- data/spec/double_entry/{aggregate_array_spec.rb → reporting/aggregate_array_spec.rb} +2 -2
- data/spec/double_entry/reporting/aggregate_spec.rb +171 -0
- data/spec/double_entry/reporting/line_aggregate_spec.rb +10 -0
- data/spec/double_entry/{month_range_spec.rb → reporting/month_range_spec.rb} +23 -21
- data/spec/double_entry/{time_range_array_spec.rb → reporting/time_range_array_spec.rb} +41 -39
- data/spec/double_entry/{time_range_spec.rb → reporting/time_range_spec.rb} +10 -9
- data/spec/double_entry/{week_range_spec.rb → reporting/week_range_spec.rb} +26 -25
- data/spec/double_entry/reporting_spec.rb +24 -0
- data/spec/double_entry/transfer_spec.rb +17 -0
- data/spec/double_entry/{line_check_spec.rb → validation/line_check_spec.rb} +17 -16
- data/spec/double_entry_spec.rb +409 -0
- data/spec/support/accounts.rb +16 -17
- metadata +70 -35
- checksums.yaml +0 -15
- data/spec/double_entry/aggregate_spec.rb +0 -168
- data/spec/double_entry/double_entry_spec.rb +0 -391
- data/spec/double_entry/line_aggregate_spec.rb +0 -8
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
|
2
|
+
module DoubleEntry::Reporting
|
3
|
+
describe TimeRangeArray do
|
3
4
|
describe '.make' do
|
4
|
-
subject(:time_range_array) {
|
5
|
+
subject(:time_range_array) { TimeRangeArray.make(range_type, start, finish) }
|
5
6
|
|
6
7
|
context 'for "hour" range type' do
|
7
8
|
let(:range_type) { 'hour' }
|
@@ -10,16 +11,16 @@ describe DoubleEntry::TimeRangeArray do
|
|
10
11
|
let(:start) { '2007-05-03 15:00:00' }
|
11
12
|
let(:finish) { '2007-05-03 18:00:00' }
|
12
13
|
it { should eq [
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
HourRange.from_time(Time.new(2007, 5, 3, 15)),
|
15
|
+
HourRange.from_time(Time.new(2007, 5, 3, 16)),
|
16
|
+
HourRange.from_time(Time.new(2007, 5, 3, 17)),
|
17
|
+
HourRange.from_time(Time.new(2007, 5, 3, 18)),
|
17
18
|
] }
|
18
19
|
end
|
19
20
|
|
20
21
|
context 'given start and finish are nil' do
|
21
22
|
it 'should raise an error' do
|
22
|
-
expect {
|
23
|
+
expect { TimeRangeArray.make(range_type, nil, nil) }.
|
23
24
|
to raise_error 'Must specify range for hour-by-hour reports'
|
24
25
|
end
|
25
26
|
end
|
@@ -32,17 +33,17 @@ describe DoubleEntry::TimeRangeArray do
|
|
32
33
|
let(:start) { '2007-05-03' }
|
33
34
|
let(:finish) { '2007-05-07' }
|
34
35
|
it { should eq [
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
DayRange.from_time(Time.new(2007, 5, 3)),
|
37
|
+
DayRange.from_time(Time.new(2007, 5, 4)),
|
38
|
+
DayRange.from_time(Time.new(2007, 5, 5)),
|
39
|
+
DayRange.from_time(Time.new(2007, 5, 6)),
|
40
|
+
DayRange.from_time(Time.new(2007, 5, 7)),
|
40
41
|
] }
|
41
42
|
end
|
42
43
|
|
43
44
|
context 'given start and finish are nil' do
|
44
45
|
it 'should raise an error' do
|
45
|
-
expect {
|
46
|
+
expect { TimeRangeArray.make(range_type, nil, nil) }.
|
46
47
|
to raise_error 'Must specify range for day-by-day reports'
|
47
48
|
end
|
48
49
|
end
|
@@ -55,16 +56,16 @@ describe DoubleEntry::TimeRangeArray do
|
|
55
56
|
let(:start) { '2007-05-03' }
|
56
57
|
let(:finish) { '2007-05-24' }
|
57
58
|
it { should eq [
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
WeekRange.from_time(Time.new(2007, 5, 3)),
|
60
|
+
WeekRange.from_time(Time.new(2007, 5, 10)),
|
61
|
+
WeekRange.from_time(Time.new(2007, 5, 17)),
|
62
|
+
WeekRange.from_time(Time.new(2007, 5, 24)),
|
62
63
|
] }
|
63
64
|
end
|
64
65
|
|
65
66
|
context 'given start and finish are nil' do
|
66
67
|
it 'should raise an error' do
|
67
|
-
expect {
|
68
|
+
expect { TimeRangeArray.make(range_type, nil, nil) }.
|
68
69
|
to raise_error 'Must specify range for week-by-week reports'
|
69
70
|
end
|
70
71
|
end
|
@@ -77,10 +78,10 @@ describe DoubleEntry::TimeRangeArray do
|
|
77
78
|
let(:start) { '2007-05-03' }
|
78
79
|
let(:finish) { '2007-08-24' }
|
79
80
|
it { should eq [
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
MonthRange.from_time(Time.new(2007, 5)),
|
82
|
+
MonthRange.from_time(Time.new(2007, 6)),
|
83
|
+
MonthRange.from_time(Time.new(2007, 7)),
|
84
|
+
MonthRange.from_time(Time.new(2007, 8)),
|
84
85
|
] }
|
85
86
|
end
|
86
87
|
|
@@ -92,15 +93,15 @@ describe DoubleEntry::TimeRangeArray do
|
|
92
93
|
before { Timecop.freeze(Time.new(2007, 4, 13)) }
|
93
94
|
|
94
95
|
it { should eq [
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
96
|
+
MonthRange.from_time(Time.new(2006, 8)),
|
97
|
+
MonthRange.from_time(Time.new(2006, 9)),
|
98
|
+
MonthRange.from_time(Time.new(2006, 10)),
|
99
|
+
MonthRange.from_time(Time.new(2006, 11)),
|
100
|
+
MonthRange.from_time(Time.new(2006, 12)),
|
101
|
+
MonthRange.from_time(Time.new(2007, 1)),
|
102
|
+
MonthRange.from_time(Time.new(2007, 2)),
|
103
|
+
MonthRange.from_time(Time.new(2007, 3)),
|
104
|
+
MonthRange.from_time(Time.new(2007, 4)),
|
104
105
|
] }
|
105
106
|
end
|
106
107
|
end
|
@@ -118,9 +119,9 @@ describe DoubleEntry::TimeRangeArray do
|
|
118
119
|
|
119
120
|
it 'takes no notice of start and finish' do
|
120
121
|
should eq [
|
121
|
-
|
122
|
-
|
123
|
-
|
122
|
+
YearRange.from_time(Time.new(2007)),
|
123
|
+
YearRange.from_time(Time.new(2008)),
|
124
|
+
YearRange.from_time(Time.new(2009)),
|
124
125
|
]
|
125
126
|
end
|
126
127
|
|
@@ -129,10 +130,10 @@ describe DoubleEntry::TimeRangeArray do
|
|
129
130
|
let(:finish) { nil }
|
130
131
|
it {
|
131
132
|
should eq [
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
133
|
+
YearRange.from_time(Time.new(2006)),
|
134
|
+
YearRange.from_time(Time.new(2007)),
|
135
|
+
YearRange.from_time(Time.new(2008)),
|
136
|
+
YearRange.from_time(Time.new(2009)),
|
136
137
|
]
|
137
138
|
}
|
138
139
|
end
|
@@ -142,8 +143,9 @@ describe DoubleEntry::TimeRangeArray do
|
|
142
143
|
|
143
144
|
context 'given an invalid range type "ueue"' do
|
144
145
|
it 'should raise an error' do
|
145
|
-
expect {
|
146
|
+
expect { TimeRangeArray.make('ueue') }.to raise_error ArgumentError
|
146
147
|
end
|
147
148
|
end
|
148
149
|
end
|
150
|
+
end
|
149
151
|
end
|
@@ -1,43 +1,44 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'spec_helper'
|
3
|
-
|
4
|
-
describe
|
3
|
+
module DoubleEntry::Reporting
|
4
|
+
describe TimeRange do
|
5
5
|
it 'should correctly calculate a month range' do
|
6
|
-
ar =
|
6
|
+
ar = TimeRange.make(:year => 2009, :month => 10)
|
7
7
|
expect(ar.start.to_s).to eq Time.mktime(2009, 10, 1, 0, 0, 0).to_s
|
8
8
|
expect(ar.finish.to_s).to eq Time.mktime(2009, 10, 31, 23, 59, 59).to_s
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should correctly calculate the beginning of the financial year" do
|
12
|
-
range =
|
12
|
+
range = TimeRange.make(:year => 2009, :month => 6).beginning_of_financial_year
|
13
13
|
expect(range.month).to eq 7
|
14
14
|
expect(range.year).to eq 2008
|
15
|
-
range =
|
15
|
+
range = TimeRange.make(:year => 2009, :month => 7).beginning_of_financial_year
|
16
16
|
expect(range.month).to eq 7
|
17
17
|
expect(range.year).to eq 2009
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should correctly calculate the current week range for New Year's Day" do
|
21
21
|
Timecop.freeze Time.mktime(2009, 1, 1) do
|
22
|
-
expect(
|
22
|
+
expect(WeekRange.current.week).to eq 1
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should correctly calculate the current week range for the first Sunday in the year after New Years" do
|
27
27
|
Timecop.freeze Time.mktime(2009, 1, 4) do
|
28
|
-
expect(
|
28
|
+
expect(WeekRange.current.week).to eq 1
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should correctly calculate the current week range for the first Monday in the year after New Years" do
|
33
33
|
Timecop.freeze Time.mktime(2009, 1, 5) do
|
34
|
-
expect(
|
34
|
+
expect(WeekRange.current.week).to eq 2
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should correctly calculate the current week range for my birthday" do
|
39
39
|
Timecop.freeze Time.mktime(2009, 3, 27) do
|
40
|
-
expect(
|
40
|
+
expect(WeekRange.current.week).to eq 13
|
41
41
|
end
|
42
42
|
end
|
43
|
+
end
|
43
44
|
end
|
@@ -1,22 +1,22 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'spec_helper'
|
3
|
-
|
4
|
-
describe
|
3
|
+
module DoubleEntry::Reporting
|
4
|
+
describe WeekRange do
|
5
5
|
|
6
6
|
it "should start week 1 of a year in the first week that has any day in the year" do
|
7
|
-
range =
|
7
|
+
range = WeekRange.new(:year => 2011, :week => 1)
|
8
8
|
expect(range.start).to eq Time.parse("2010-12-27 00:00:00")
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should handle times in the last week of the year properly" do
|
12
|
-
range =
|
12
|
+
range = WeekRange.from_time(Time.parse("2010-12-29 11:30:00"))
|
13
13
|
expect(range.year).to eq 2011
|
14
14
|
expect(range.week).to eq 1
|
15
15
|
expect(range.start).to eq Time.parse("2010-12-27 00:00:00")
|
16
16
|
end
|
17
17
|
|
18
18
|
describe "::from_time" do
|
19
|
-
subject(:from_time) {
|
19
|
+
subject(:from_time) { WeekRange.from_time(given_time) }
|
20
20
|
|
21
21
|
context "given the Time 31st March 2012" do
|
22
22
|
let(:given_time) { Time.new(2012, 3, 31) }
|
@@ -32,17 +32,17 @@ describe DoubleEntry::WeekRange do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
describe "::reportable_weeks" do
|
35
|
-
subject(:reportable_weeks) {
|
35
|
+
subject(:reportable_weeks) { WeekRange.reportable_weeks }
|
36
36
|
|
37
37
|
context "The date is 1st Feb 1970" do
|
38
38
|
before { Timecop.freeze(Time.new(1970, 2, 1)) }
|
39
39
|
|
40
40
|
it { should eq [
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
WeekRange.new(year: 1970, week: 1),
|
42
|
+
WeekRange.new(year: 1970, week: 2),
|
43
|
+
WeekRange.new(year: 1970, week: 3),
|
44
|
+
WeekRange.new(year: 1970, week: 4),
|
45
|
+
WeekRange.new(year: 1970, week: 5),
|
46
46
|
] }
|
47
47
|
|
48
48
|
context "My business started on 25th Jan 1970" do
|
@@ -53,8 +53,8 @@ describe DoubleEntry::WeekRange do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it { should eq [
|
56
|
-
|
57
|
-
|
56
|
+
WeekRange.new(year: 1970, week: 4),
|
57
|
+
WeekRange.new(year: 1970, week: 5),
|
58
58
|
] }
|
59
59
|
end
|
60
60
|
end
|
@@ -62,27 +62,28 @@ describe DoubleEntry::WeekRange do
|
|
62
62
|
context "The date is 1st Jan 1970" do
|
63
63
|
before { Timecop.freeze(Time.new(1970, 1, 1)) }
|
64
64
|
|
65
|
-
it { should eq [
|
65
|
+
it { should eq [ WeekRange.new(year: 1970, week: 1) ] }
|
66
66
|
end
|
67
67
|
|
68
68
|
context "Given a start time of 3rd Dec 1982" do
|
69
|
-
subject(:reportable_weeks) {
|
69
|
+
subject(:reportable_weeks) { WeekRange.reportable_weeks(from: Time.new(1982, 12, 3)) }
|
70
70
|
|
71
71
|
context "The date is 12nd Jan 1983" do
|
72
72
|
before { Timecop.freeze(Time.new(1983, 2, 2)) }
|
73
73
|
it { should eq [
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
74
|
+
WeekRange.new(year: 1982, week: 49),
|
75
|
+
WeekRange.new(year: 1982, week: 50),
|
76
|
+
WeekRange.new(year: 1982, week: 51),
|
77
|
+
WeekRange.new(year: 1982, week: 52),
|
78
|
+
WeekRange.new(year: 1983, week: 1),
|
79
|
+
WeekRange.new(year: 1983, week: 2),
|
80
|
+
WeekRange.new(year: 1983, week: 3),
|
81
|
+
WeekRange.new(year: 1983, week: 4),
|
82
|
+
WeekRange.new(year: 1983, week: 5),
|
83
|
+
WeekRange.new(year: 1983, week: 6),
|
84
84
|
] }
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
|
+
end
|
88
89
|
end
|
@@ -22,4 +22,28 @@ describe DoubleEntry::Reporting do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
describe "::scopes_with_minimum_balance_for_account" do
|
26
|
+
subject(:scopes) { DoubleEntry::Reporting.scopes_with_minimum_balance_for_account(minimum_balance, :checking) }
|
27
|
+
|
28
|
+
context "a 'checking' account with balance $100" do
|
29
|
+
let!(:user) { User.make!(:checking_balance => Money.new(100_00)) }
|
30
|
+
|
31
|
+
context "when searching for balance $99" do
|
32
|
+
let(:minimum_balance) { Money.new(99_00) }
|
33
|
+
it { should include user.id }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when searching for balance $100" do
|
37
|
+
let(:minimum_balance) { Money.new(100_00) }
|
38
|
+
it { should include user.id }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when searching for balance $101" do
|
42
|
+
let(:minimum_balance) { Money.new(101_00) }
|
43
|
+
it { should_not include user.id }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
25
49
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
describe DoubleEntry::Transfer::Set do
|
4
|
+
describe "#define" do
|
5
|
+
before do
|
6
|
+
subject.define(
|
7
|
+
:code => "code",
|
8
|
+
:from => double(:identifier => "from"),
|
9
|
+
:to => double(:identifier => "to"),
|
10
|
+
)
|
11
|
+
end
|
12
|
+
its(:first) { should be_a DoubleEntry::Transfer }
|
13
|
+
its("first.code") { should eq "code" }
|
14
|
+
its("first.from.identifier") { should eq "from" }
|
15
|
+
its("first.to.identifier") { should eq "to" }
|
16
|
+
end
|
17
|
+
end
|
@@ -1,32 +1,32 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'spec_helper'
|
3
|
-
|
4
|
-
describe
|
3
|
+
module DoubleEntry::Validation
|
4
|
+
describe LineCheck do
|
5
5
|
|
6
6
|
describe '#last' do
|
7
7
|
|
8
8
|
context 'Given some checks have been created' do
|
9
9
|
before do
|
10
10
|
Timecop.freeze 3.minutes.ago do
|
11
|
-
|
11
|
+
LineCheck.create! :last_line_id => 100, :errors_found => false, :log => ''
|
12
12
|
end
|
13
13
|
Timecop.freeze 1.minute.ago do
|
14
|
-
|
14
|
+
LineCheck.create! :last_line_id => 300, :errors_found => false, :log => ''
|
15
15
|
end
|
16
16
|
Timecop.freeze 2.minutes.ago do
|
17
|
-
|
17
|
+
LineCheck.create! :last_line_id => 200, :errors_found => false, :log => ''
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'should find the newest LineCheck created (by creation_date)' do
|
22
|
-
expect(
|
22
|
+
expect(LineCheck.last.last_line_id).to eq 300
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
27
27
|
|
28
28
|
describe '#perform!' do
|
29
|
-
subject(:performed_line_check) {
|
29
|
+
subject(:performed_line_check) { LineCheck.perform! }
|
30
30
|
|
31
31
|
context 'Given a user with 100 dollars' do
|
32
32
|
before { User.make!(:savings_balance => Money.new(100_00)) }
|
@@ -34,23 +34,23 @@ describe DoubleEntry::LineCheck do
|
|
34
34
|
context 'And all is consistent' do
|
35
35
|
|
36
36
|
context 'And all lines have been checked' do
|
37
|
-
before {
|
37
|
+
before { LineCheck.perform! }
|
38
38
|
|
39
39
|
it { should be_nil }
|
40
40
|
|
41
41
|
it 'should not persist a new LineCheck' do
|
42
42
|
expect {
|
43
|
-
|
44
|
-
}.to_not change {
|
43
|
+
LineCheck.perform!
|
44
|
+
}.to_not change { LineCheck.count }
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
it { should be_instance_of
|
48
|
+
it { should be_instance_of LineCheck }
|
49
49
|
its(:errors_found) { should eq false }
|
50
50
|
|
51
51
|
it 'should persist the LineCheck' do
|
52
|
-
line_check =
|
53
|
-
expect(
|
52
|
+
line_check = LineCheck.perform!
|
53
|
+
expect(LineCheck.last).to eq line_check
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -62,7 +62,7 @@ describe DoubleEntry::LineCheck do
|
|
62
62
|
|
63
63
|
it 'should correct the running balance' do
|
64
64
|
expect {
|
65
|
-
|
65
|
+
LineCheck.perform!
|
66
66
|
}.to change { DoubleEntry::Line.order(:id).first.balance }.by Money.new(-1)
|
67
67
|
end
|
68
68
|
end
|
@@ -74,15 +74,16 @@ describe DoubleEntry::LineCheck do
|
|
74
74
|
|
75
75
|
it 'should correct the account balance' do
|
76
76
|
expect {
|
77
|
-
|
77
|
+
LineCheck.perform!
|
78
78
|
}.to change { DoubleEntry::AccountBalance.order(:id).first.balance }.by Money.new(-1)
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
83
|
it "has a table name prefixed with double_entry_" do
|
84
|
-
expect(
|
84
|
+
expect(LineCheck.table_name).to eq "double_entry_line_checks"
|
85
85
|
end
|
86
86
|
|
87
87
|
end
|
88
|
+
end
|
88
89
|
end
|