double_entry 0.10.3 → 1.0.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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +5 -1
- data/README.md +16 -0
- data/double_entry.gemspec +35 -0
- data/lib/double_entry.rb +1 -0
- data/lib/double_entry/line.rb +1 -0
- data/lib/double_entry/line_metadata.rb +18 -0
- data/lib/double_entry/locking.rb +11 -0
- data/lib/double_entry/reporting.rb +26 -14
- data/lib/double_entry/reporting/aggregate.rb +11 -15
- data/lib/double_entry/reporting/aggregate_array.rb +1 -1
- data/lib/double_entry/reporting/line_aggregate.rb +2 -23
- data/lib/double_entry/reporting/line_aggregate_filter.rb +81 -0
- data/lib/double_entry/transfer.rb +42 -25
- data/lib/double_entry/version.rb +1 -1
- data/lib/generators/double_entry/install/templates/migration.rb +10 -0
- data/spec/double_entry/locking_spec.rb +29 -0
- data/spec/double_entry/performance/double_entry_performance_spec.rb +32 -0
- data/spec/double_entry/performance/reporting/aggregate_performance_spec.rb +50 -0
- data/spec/double_entry/reporting/aggregate_array_spec.rb +10 -10
- data/spec/double_entry/reporting/aggregate_spec.rb +57 -114
- data/spec/double_entry/reporting/line_aggregate_filter_spec.rb +90 -0
- data/spec/double_entry/reporting/line_aggregate_spec.rb +35 -7
- data/spec/double_entry/reporting_spec.rb +136 -0
- data/spec/double_entry/transfer_spec.rb +58 -1
- data/spec/support/performance_helper.rb +26 -0
- data/spec/support/schema.rb +9 -0
- metadata +124 -4
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
RSpec.describe DoubleEntry::Reporting::LineAggregateFilter do
|
3
|
+
describe '.filter' do
|
4
|
+
let(:function) { :sum }
|
5
|
+
let(:account) { :account }
|
6
|
+
let(:code) { :transfer_code }
|
7
|
+
let(:filter_criteria) { nil }
|
8
|
+
let(:start) { Time.parse('2014-07-27 10:55:44 +1000') }
|
9
|
+
let(:finish) { Time.parse('2015-07-27 10:55:44 +1000') }
|
10
|
+
let(:range) do
|
11
|
+
instance_double(DoubleEntry::Reporting::MonthRange, :start => start, :finish => finish)
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:lines_scope) { spy(DoubleEntry::Line) }
|
15
|
+
|
16
|
+
subject(:filter) do
|
17
|
+
DoubleEntry::Reporting::LineAggregateFilter.new(account, code, range, filter_criteria)
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
stub_const('DoubleEntry::Line', lines_scope)
|
22
|
+
|
23
|
+
allow(DoubleEntry::LineMetadata).to receive(:table_name).and_return('double_entry_line_metadata')
|
24
|
+
|
25
|
+
allow(lines_scope).to receive(:where).and_return(lines_scope)
|
26
|
+
allow(lines_scope).to receive(:joins).and_return(lines_scope)
|
27
|
+
allow(lines_scope).to receive(:ten_dollar_purchases).and_return(lines_scope)
|
28
|
+
allow(lines_scope).to receive(:ten_dollar_purchases_by_category).and_return(lines_scope)
|
29
|
+
|
30
|
+
filter.filter
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with named scopes specified' do
|
34
|
+
let(:filter_criteria) do
|
35
|
+
[
|
36
|
+
# an example of calling a named scope called with arguments
|
37
|
+
{
|
38
|
+
:scope => {
|
39
|
+
:name => :ten_dollar_purchases_by_category,
|
40
|
+
:arguments => [:cat_videos, :cat_pictures],
|
41
|
+
},
|
42
|
+
},
|
43
|
+
# an example of calling a named scope with no arguments
|
44
|
+
{
|
45
|
+
:scope => {
|
46
|
+
:name => :ten_dollar_purchases,
|
47
|
+
},
|
48
|
+
},
|
49
|
+
# an example of providing a single metadatum criteria to filter on
|
50
|
+
{
|
51
|
+
:metadata => {
|
52
|
+
:meme => 'business_cat',
|
53
|
+
},
|
54
|
+
},
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'filters by all the scopes provided' do
|
59
|
+
expect(DoubleEntry::Line).to have_received(:ten_dollar_purchases)
|
60
|
+
expect(DoubleEntry::Line).to have_received(:ten_dollar_purchases_by_category).
|
61
|
+
with(:cat_videos, :cat_pictures)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'filters by all the metadata provided' do
|
65
|
+
expect(DoubleEntry::Line).to have_received(:joins).with(:metadata)
|
66
|
+
expect(DoubleEntry::Line).to have_received(:where).
|
67
|
+
with(:double_entry_line_metadata => { :key => :meme, :value => 'business_cat' })
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with a code specified' do
|
72
|
+
let(:code) { :transfer_code }
|
73
|
+
|
74
|
+
it 'retrieves the appropriate lines for aggregation' do
|
75
|
+
expect(DoubleEntry::Line).to have_received(:where).with(:account => account)
|
76
|
+
expect(DoubleEntry::Line).to have_received(:where).with(:created_at => start..finish)
|
77
|
+
expect(DoubleEntry::Line).to have_received(:where).with(:code => code)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'with no code specified' do
|
82
|
+
let(:code) { nil }
|
83
|
+
|
84
|
+
it 'retrieves the appropriate lines for aggregation' do
|
85
|
+
expect(DoubleEntry::Line).to have_received(:where).with(:account => account)
|
86
|
+
expect(DoubleEntry::Line).to have_received(:where).with(:created_at => start..finish)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -1,11 +1,39 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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)
|
9
37
|
end
|
10
38
|
end
|
11
39
|
end
|
@@ -42,4 +42,140 @@ RSpec.describe DoubleEntry::Reporting do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
describe '::aggregate' do
|
47
|
+
before do
|
48
|
+
# get rid of "helpful" predefined config
|
49
|
+
@config_accounts = DoubleEntry.configuration.accounts
|
50
|
+
@config_transfers = DoubleEntry.configuration.transfers
|
51
|
+
DoubleEntry.configuration.accounts = DoubleEntry::Account::Set.new
|
52
|
+
DoubleEntry.configuration.transfers = DoubleEntry::Transfer::Set.new
|
53
|
+
|
54
|
+
DoubleEntry.configure do |config|
|
55
|
+
config.define_accounts do |accounts|
|
56
|
+
accounts.define(:identifier => :savings)
|
57
|
+
accounts.define(:identifier => :cash)
|
58
|
+
accounts.define(:identifier => :credit)
|
59
|
+
end
|
60
|
+
|
61
|
+
config.define_transfers do |transfers|
|
62
|
+
transfers.define(:from => :savings, :to => :cash, :code => :spend)
|
63
|
+
transfers.define(:from => :cash, :to => :savings, :code => :save)
|
64
|
+
transfers.define(:from => :cash, :to => :credit, :code => :bill)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
cash = DoubleEntry.account(:cash)
|
69
|
+
savings = DoubleEntry.account(:savings)
|
70
|
+
credit = DoubleEntry.account(:credit)
|
71
|
+
DoubleEntry.transfer(Money.new(10_00), :from => cash, :to => savings, :code => :save, :metadata => { :reason => 'payday' })
|
72
|
+
DoubleEntry.transfer(Money.new(10_00), :from => cash, :to => savings, :code => :save, :metadata => { :reason => 'payday' })
|
73
|
+
DoubleEntry.transfer(Money.new(20_00), :from => cash, :to => savings, :code => :save)
|
74
|
+
DoubleEntry.transfer(Money.new(20_00), :from => cash, :to => savings, :code => :save)
|
75
|
+
DoubleEntry.transfer(Money.new(30_00), :from => cash, :to => credit, :code => :bill)
|
76
|
+
DoubleEntry.transfer(Money.new(40_00), :from => cash, :to => credit, :code => :bill)
|
77
|
+
DoubleEntry.transfer(Money.new(50_00), :from => savings, :to => cash, :code => :spend)
|
78
|
+
DoubleEntry.transfer(Money.new(60_00), :from => savings, :to => cash, :code => :spend, :metadata => { :category => 'entertainment' })
|
79
|
+
end
|
80
|
+
|
81
|
+
after do
|
82
|
+
# restore "helpful" predefined config
|
83
|
+
DoubleEntry.configuration.accounts = @config_accounts
|
84
|
+
DoubleEntry.configuration.transfers = @config_transfers
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'filter solely on transaction identifiers and time' do
|
88
|
+
let(:function) { :sum }
|
89
|
+
let(:account) { :savings }
|
90
|
+
let(:code) { :save }
|
91
|
+
let(:range) { DoubleEntry::Reporting::MonthRange.current }
|
92
|
+
|
93
|
+
subject(:aggregate) do
|
94
|
+
DoubleEntry::Reporting.aggregate(function, account, code, range)
|
95
|
+
end
|
96
|
+
|
97
|
+
specify 'Total attempted to save' do
|
98
|
+
expect(aggregate).to eq(Money.new(60_00))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'filter by named scope that does not take arguments' do
|
103
|
+
let(:function) { :sum }
|
104
|
+
let(:account) { :savings }
|
105
|
+
let(:code) { :save }
|
106
|
+
let(:range) { DoubleEntry::Reporting::MonthRange.current }
|
107
|
+
|
108
|
+
subject(:aggregate) do
|
109
|
+
DoubleEntry::Reporting.aggregate(
|
110
|
+
function, account, code, range,
|
111
|
+
:filter => [
|
112
|
+
:scope => {
|
113
|
+
:name => :ten_dollar_transfers,
|
114
|
+
},
|
115
|
+
]
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
119
|
+
before do
|
120
|
+
DoubleEntry::Line.class_eval do
|
121
|
+
scope :ten_dollar_transfers, -> { where(:amount => Money.new(10_00).fractional) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
specify 'Total amount of $10 transfers attempted to save' do
|
126
|
+
expect(aggregate).to eq(Money.new(20_00))
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'filter by named scope that takes arguments' do
|
131
|
+
let(:function) { :sum }
|
132
|
+
let(:account) { :savings }
|
133
|
+
let(:code) { :save }
|
134
|
+
let(:range) { DoubleEntry::Reporting::MonthRange.current }
|
135
|
+
|
136
|
+
subject(:aggregate) do
|
137
|
+
DoubleEntry::Reporting.aggregate(
|
138
|
+
function, account, code, range,
|
139
|
+
:filter => [
|
140
|
+
:scope => {
|
141
|
+
:name => :specific_transfer_amount,
|
142
|
+
:arguments => [Money.new(20_00)],
|
143
|
+
},
|
144
|
+
]
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
before do
|
149
|
+
DoubleEntry::Line.class_eval do
|
150
|
+
scope :specific_transfer_amount, ->(amount) { where(:amount => amount.fractional) }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
specify 'Total amount of transfers of $20 attempted to save' do
|
155
|
+
expect(aggregate).to eq(Money.new(40_00))
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe 'filter by metadata' do
|
160
|
+
let(:function) { :sum }
|
161
|
+
let(:account) { :savings }
|
162
|
+
let(:code) { :save }
|
163
|
+
let(:range) { DoubleEntry::Reporting::MonthRange.current }
|
164
|
+
|
165
|
+
subject(:aggregate) do
|
166
|
+
DoubleEntry::Reporting.aggregate(
|
167
|
+
function, account, code, range,
|
168
|
+
:filter => [
|
169
|
+
:metadata => {
|
170
|
+
:reason => 'payday',
|
171
|
+
},
|
172
|
+
]
|
173
|
+
)
|
174
|
+
end
|
175
|
+
|
176
|
+
specify 'Total amount of transfers saved because payday' do
|
177
|
+
expect(aggregate).to eq(Money.new(20_00))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
45
181
|
end
|
@@ -17,13 +17,70 @@ module DoubleEntry
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
describe '::transfer' do
|
21
|
+
let(:amount) { Money.new(10_00) }
|
22
|
+
let(:user) { User.make! }
|
23
|
+
let(:test) { DoubleEntry.account(:test, :scope => user) }
|
24
|
+
let(:savings) { DoubleEntry.account(:savings, :scope => user) }
|
25
|
+
let(:new_lines) { Line.all[-2..-1] }
|
26
|
+
|
27
|
+
subject(:transfer) { Transfer.transfer(amount, options) }
|
28
|
+
|
29
|
+
context 'without metadata' do
|
30
|
+
let(:options) { { :from => test, :to => savings, :code => :bonus } }
|
31
|
+
|
32
|
+
it 'creates lines' do
|
33
|
+
expect { transfer }.to change { Line.count }.by 2
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'does not create metadata lines' do
|
37
|
+
expect { transfer }.not_to change { LineMetadata.count }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with metadata' do
|
42
|
+
let(:options) { { :from => test, :to => savings, :code => :bonus, :metadata => { :country => 'AU', :tax => 'GST' } } }
|
43
|
+
let(:new_metadata) { LineMetadata.all[-4..-1] }
|
44
|
+
|
45
|
+
it 'creates metadata lines' do
|
46
|
+
expect { transfer }.to change { LineMetadata.count }.by 4
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'associates the metadata lines with the transfer lines' do
|
50
|
+
transfer
|
51
|
+
expect(new_metadata.count { |meta| meta.line == new_lines.first }).to be 2
|
52
|
+
expect(new_metadata.count { |meta| meta.line == new_lines.last }).to be 2
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'stores the first key/value pair' do
|
56
|
+
transfer
|
57
|
+
countries = new_metadata.select { |meta| meta.key == :country }
|
58
|
+
expect(countries.size).to be 2
|
59
|
+
expect(countries.count { |meta| meta.value == 'AU' }).to be 2
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'associates the first key/value pair with both lines' do
|
63
|
+
transfer
|
64
|
+
countries = new_metadata.select { |meta| meta.key == :country }
|
65
|
+
expect(countries.map(&:line).uniq.size).to be 2
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'stores another key/value pair' do
|
69
|
+
transfer
|
70
|
+
taxes = new_metadata.select { |meta| meta.key == :tax }
|
71
|
+
expect(taxes.size).to be 2
|
72
|
+
expect(taxes.count { |meta| meta.value == 'GST' }).to be 2
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
20
77
|
describe Transfer::Set do
|
21
78
|
describe '#define' do
|
22
79
|
before do
|
23
80
|
subject.define(
|
24
81
|
:code => 'code',
|
25
82
|
:from => double(:identifier => 'from'),
|
26
|
-
:to
|
83
|
+
:to => double(:identifier => 'to'),
|
27
84
|
)
|
28
85
|
end
|
29
86
|
its(:first) { should be_a Transfer }
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PerformanceHelper
|
2
|
+
require 'ruby-prof'
|
3
|
+
|
4
|
+
def start_profiling(measure_mode = RubyProf::PROCESS_TIME)
|
5
|
+
RubyProf.measure_mode = measure_mode
|
6
|
+
RubyProf.start
|
7
|
+
end
|
8
|
+
|
9
|
+
def stop_profiling(profile_name = nil)
|
10
|
+
result = RubyProf.stop
|
11
|
+
puts "#{profile_name} Time: #{format('%#.3g', total_time(result))}s"
|
12
|
+
unless ENV.fetch('CI', false)
|
13
|
+
if profile_name
|
14
|
+
outdir = './profiles'
|
15
|
+
Dir.mkdir(outdir) unless Dir.exist?(outdir)
|
16
|
+
printer = RubyProf::MultiPrinter.new(result)
|
17
|
+
printer.print(:path => outdir, :profile => profile_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
result
|
21
|
+
end
|
22
|
+
|
23
|
+
def total_time(result)
|
24
|
+
result.threads.inject(0) { |time, thread| time + thread.total_time }
|
25
|
+
end
|
26
|
+
end
|
data/spec/support/schema.rb
CHANGED
@@ -55,6 +55,15 @@ ActiveRecord::Schema.define do
|
|
55
55
|
t.timestamps :null => false
|
56
56
|
end
|
57
57
|
|
58
|
+
create_table "double_entry_line_metadata", :force => true do |t|
|
59
|
+
t.integer "line_id", :null => false
|
60
|
+
t.string "key", :limit => 48, :null => false
|
61
|
+
t.string "value", :limit => 64, :null => false
|
62
|
+
t.timestamps :null => false
|
63
|
+
end
|
64
|
+
|
65
|
+
add_index "double_entry_line_metadata", ["line_id", "key", "value"], :name => "lines_meta_line_id_key_value_idx"
|
66
|
+
|
58
67
|
# test table only
|
59
68
|
create_table "users", :force => true do |t|
|
60
69
|
t.string "username", :null => false
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: double_entry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anthony Sellitti
|
@@ -15,7 +15,7 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date: 2015-
|
18
|
+
date: 2015-08-04 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: money
|
@@ -241,6 +241,90 @@ dependencies:
|
|
241
241
|
- - "~>"
|
242
242
|
- !ruby/object:Gem::Version
|
243
243
|
version: 0.32.0
|
244
|
+
- !ruby/object:Gem::Dependency
|
245
|
+
name: pry
|
246
|
+
requirement: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
type: :development
|
252
|
+
prerelease: false
|
253
|
+
version_requirements: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - ">="
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0'
|
258
|
+
- !ruby/object:Gem::Dependency
|
259
|
+
name: pry-doc
|
260
|
+
requirement: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - ">="
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '0'
|
265
|
+
type: :development
|
266
|
+
prerelease: false
|
267
|
+
version_requirements: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - ">="
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
- !ruby/object:Gem::Dependency
|
273
|
+
name: pry-byebug
|
274
|
+
requirement: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ">="
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
279
|
+
type: :development
|
280
|
+
prerelease: false
|
281
|
+
version_requirements: !ruby/object:Gem::Requirement
|
282
|
+
requirements:
|
283
|
+
- - ">="
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '0'
|
286
|
+
- !ruby/object:Gem::Dependency
|
287
|
+
name: pry-stack_explorer
|
288
|
+
requirement: !ruby/object:Gem::Requirement
|
289
|
+
requirements:
|
290
|
+
- - ">="
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: '0'
|
293
|
+
type: :development
|
294
|
+
prerelease: false
|
295
|
+
version_requirements: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ">="
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '0'
|
300
|
+
- !ruby/object:Gem::Dependency
|
301
|
+
name: awesome_print
|
302
|
+
requirement: !ruby/object:Gem::Requirement
|
303
|
+
requirements:
|
304
|
+
- - ">="
|
305
|
+
- !ruby/object:Gem::Version
|
306
|
+
version: '0'
|
307
|
+
type: :development
|
308
|
+
prerelease: false
|
309
|
+
version_requirements: !ruby/object:Gem::Requirement
|
310
|
+
requirements:
|
311
|
+
- - ">="
|
312
|
+
- !ruby/object:Gem::Version
|
313
|
+
version: '0'
|
314
|
+
- !ruby/object:Gem::Dependency
|
315
|
+
name: ruby-prof
|
316
|
+
requirement: !ruby/object:Gem::Requirement
|
317
|
+
requirements:
|
318
|
+
- - ">="
|
319
|
+
- !ruby/object:Gem::Version
|
320
|
+
version: '0'
|
321
|
+
type: :development
|
322
|
+
prerelease: false
|
323
|
+
version_requirements: !ruby/object:Gem::Requirement
|
324
|
+
requirements:
|
325
|
+
- - ">="
|
326
|
+
- !ruby/object:Gem::Version
|
327
|
+
version: '0'
|
244
328
|
description:
|
245
329
|
email:
|
246
330
|
- anthony.sellitti@envato.com
|
@@ -275,6 +359,7 @@ files:
|
|
275
359
|
- lib/double_entry/configuration.rb
|
276
360
|
- lib/double_entry/errors.rb
|
277
361
|
- lib/double_entry/line.rb
|
362
|
+
- lib/double_entry/line_metadata.rb
|
278
363
|
- lib/double_entry/locking.rb
|
279
364
|
- lib/double_entry/reporting.rb
|
280
365
|
- lib/double_entry/reporting/aggregate.rb
|
@@ -282,6 +367,7 @@ files:
|
|
282
367
|
- lib/double_entry/reporting/day_range.rb
|
283
368
|
- lib/double_entry/reporting/hour_range.rb
|
284
369
|
- lib/double_entry/reporting/line_aggregate.rb
|
370
|
+
- lib/double_entry/reporting/line_aggregate_filter.rb
|
285
371
|
- lib/double_entry/reporting/month_range.rb
|
286
372
|
- lib/double_entry/reporting/time_range.rb
|
287
373
|
- lib/double_entry/reporting/time_range_array.rb
|
@@ -302,8 +388,11 @@ files:
|
|
302
388
|
- spec/double_entry/configuration_spec.rb
|
303
389
|
- spec/double_entry/line_spec.rb
|
304
390
|
- spec/double_entry/locking_spec.rb
|
391
|
+
- spec/double_entry/performance/double_entry_performance_spec.rb
|
392
|
+
- spec/double_entry/performance/reporting/aggregate_performance_spec.rb
|
305
393
|
- spec/double_entry/reporting/aggregate_array_spec.rb
|
306
394
|
- spec/double_entry/reporting/aggregate_spec.rb
|
395
|
+
- spec/double_entry/reporting/line_aggregate_filter_spec.rb
|
307
396
|
- spec/double_entry/reporting/line_aggregate_spec.rb
|
308
397
|
- spec/double_entry/reporting/month_range_spec.rb
|
309
398
|
- spec/double_entry/reporting/time_range_array_spec.rb
|
@@ -323,12 +412,38 @@ files:
|
|
323
412
|
- spec/support/gemfiles/Gemfile.rails-3.2.x
|
324
413
|
- spec/support/gemfiles/Gemfile.rails-4.1.x
|
325
414
|
- spec/support/gemfiles/Gemfile.rails-4.2.x
|
415
|
+
- spec/support/performance_helper.rb
|
326
416
|
- spec/support/reporting_configuration.rb
|
327
417
|
- spec/support/schema.rb
|
328
418
|
homepage: https://github.com/envato/double_entry
|
329
419
|
licenses: []
|
330
420
|
metadata: {}
|
331
|
-
post_install_message:
|
421
|
+
post_install_message: |
|
422
|
+
Please note the following changes in DoubleEntry:
|
423
|
+
- New table `double_entry_line_metadata` has been introduced and is *required* for
|
424
|
+
aggregate reporting filtering to work. Existing applications must manually manage
|
425
|
+
this change via a migration similar to the following:
|
426
|
+
|
427
|
+
class CreateDoubleEntryLineMetadata < ActiveRecord::Migration
|
428
|
+
def self.up
|
429
|
+
create_table "#{DoubleEntry.table_name_prefix}line_metadata", :force => true do |t|
|
430
|
+
t.integer "line_id", :null => false
|
431
|
+
t.string "key", :limit => 48, :null => false
|
432
|
+
t.string "value", :limit => 64, :null => false
|
433
|
+
t.timestamps :null => false
|
434
|
+
end
|
435
|
+
|
436
|
+
add_index "#{DoubleEntry.table_name_prefix}line_metadata",
|
437
|
+
["line_id", "key", "value"],
|
438
|
+
:name => "lines_meta_line_id_key_value_idx"
|
439
|
+
end
|
440
|
+
|
441
|
+
def self.down
|
442
|
+
drop_table "#{DoubleEntry.table_name_prefix}line_metadata"
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
Please ensure that you update your database accordingly.
|
332
447
|
rdoc_options: []
|
333
448
|
require_paths:
|
334
449
|
- lib
|
@@ -344,7 +459,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
344
459
|
version: '0'
|
345
460
|
requirements: []
|
346
461
|
rubyforge_project:
|
347
|
-
rubygems_version: 2.
|
462
|
+
rubygems_version: 2.2.2
|
348
463
|
signing_key:
|
349
464
|
specification_version: 4
|
350
465
|
summary: Tools to build your double entry financial ledger
|
@@ -356,8 +471,11 @@ test_files:
|
|
356
471
|
- spec/double_entry/configuration_spec.rb
|
357
472
|
- spec/double_entry/line_spec.rb
|
358
473
|
- spec/double_entry/locking_spec.rb
|
474
|
+
- spec/double_entry/performance/double_entry_performance_spec.rb
|
475
|
+
- spec/double_entry/performance/reporting/aggregate_performance_spec.rb
|
359
476
|
- spec/double_entry/reporting/aggregate_array_spec.rb
|
360
477
|
- spec/double_entry/reporting/aggregate_spec.rb
|
478
|
+
- spec/double_entry/reporting/line_aggregate_filter_spec.rb
|
361
479
|
- spec/double_entry/reporting/line_aggregate_spec.rb
|
362
480
|
- spec/double_entry/reporting/month_range_spec.rb
|
363
481
|
- spec/double_entry/reporting/time_range_array_spec.rb
|
@@ -377,5 +495,7 @@ test_files:
|
|
377
495
|
- spec/support/gemfiles/Gemfile.rails-3.2.x
|
378
496
|
- spec/support/gemfiles/Gemfile.rails-4.1.x
|
379
497
|
- spec/support/gemfiles/Gemfile.rails-4.2.x
|
498
|
+
- spec/support/performance_helper.rb
|
380
499
|
- spec/support/reporting_configuration.rb
|
381
500
|
- spec/support/schema.rb
|
501
|
+
has_rdoc:
|