double_entry 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|