borutus 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +62 -64
- data/app/models/borutus/account.rb +97 -86
- data/app/models/borutus/amount.rb +9 -4
- data/app/models/borutus/amounts_extension.rb +1 -1
- data/app/services/borutus/accounts/build_running_balance_query.rb +73 -0
- data/db/migrate/20191025095830_add_borutus_amount_counter_cache.rb +15 -0
- data/lib/borutus.rb +1 -0
- data/lib/borutus/version.rb +1 -1
- data/spec/controllers/accounts_controller_spec.rb +1 -1
- data/spec/controllers/entries_controller_spec.rb +1 -1
- data/spec/controllers/reports_controller_spec.rb +1 -1
- data/spec/factories/account_factory.rb +13 -13
- data/spec/factories/amount_factory.rb +13 -13
- data/spec/factories/entry_factory.rb +11 -8
- data/spec/models/account_spec.rb +98 -53
- data/spec/models/amount_spec.rb +1 -1
- data/spec/models/entry_spec.rb +54 -50
- data/spec/models/tenancy_spec.rb +6 -6
- data/spec/routing/entries_routing_spec.rb +1 -1
- data/spec/spec_helper.rb +16 -14
- data/spec/support/account_shared_examples.rb +3 -3
- data/spec/support/amount_shared_examples.rb +1 -1
- data/spec/support/factory_bot_helpers.rb +8 -0
- metadata +44 -25
- data/spec/support/factory_girl_helpers.rb +0 -8
data/spec/models/amount_spec.rb
CHANGED
data/spec/models/entry_spec.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
module Borutus
|
4
4
|
describe Entry do
|
5
|
-
let(:entry) {
|
5
|
+
let(:entry) { FactoryBot.build(:entry) }
|
6
6
|
subject { entry }
|
7
7
|
|
8
8
|
it { is_expected.not_to be_valid }
|
9
9
|
|
10
10
|
context "with credit and debit" do
|
11
|
-
let(:entry) {
|
11
|
+
let(:entry) { FactoryBot.build(:entry_with_credit_and_debit) }
|
12
12
|
it { is_expected.to be_valid }
|
13
13
|
|
14
14
|
it "should require a description" do
|
@@ -18,35 +18,35 @@ module Borutus
|
|
18
18
|
end
|
19
19
|
|
20
20
|
context "with a debit" do
|
21
|
-
before
|
22
|
-
entry.debit_amounts <<
|
23
|
-
|
21
|
+
before do
|
22
|
+
entry.debit_amounts << FactoryBot.build(:debit_amount, entry: entry)
|
23
|
+
end
|
24
24
|
it { is_expected.not_to be_valid }
|
25
25
|
|
26
26
|
context "with an invalid credit" do
|
27
27
|
before {
|
28
|
-
entry.credit_amounts <<
|
28
|
+
entry.credit_amounts << FactoryBot.build(:credit_amount, entry: entry, amount: nil)
|
29
29
|
}
|
30
30
|
it { is_expected.not_to be_valid }
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
context "with a credit" do
|
35
|
-
before
|
36
|
-
entry.credit_amounts <<
|
37
|
-
|
35
|
+
before do
|
36
|
+
entry.credit_amounts << FactoryBot.build(:credit_amount, entry: entry)
|
37
|
+
end
|
38
38
|
it { is_expected.not_to be_valid }
|
39
39
|
|
40
40
|
context "with an invalid debit" do
|
41
|
-
before
|
42
|
-
entry.debit_amounts <<
|
43
|
-
|
41
|
+
before do
|
42
|
+
entry.debit_amounts << FactoryBot.build(:debit_amount, entry: entry, amount: nil)
|
43
|
+
end
|
44
44
|
it { is_expected.not_to be_valid }
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
context "without a date" do
|
49
|
-
let(:entry) {
|
49
|
+
let(:entry) { FactoryBot.build(:entry_with_credit_and_debit, date: nil) }
|
50
50
|
|
51
51
|
context "should assign a default date before being saved" do
|
52
52
|
before { entry.save! }
|
@@ -55,44 +55,50 @@ module Borutus
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should require the debit and credit amounts to cancel" do
|
58
|
-
entry.credit_amounts <<
|
59
|
-
entry.debit_amounts <<
|
58
|
+
entry.credit_amounts << FactoryBot.build(:credit_amount, amount: 100, entry: entry)
|
59
|
+
entry.debit_amounts << FactoryBot.build(:debit_amount, amount: 200, entry: entry)
|
60
60
|
expect(entry).not_to be_valid
|
61
|
-
expect(entry.errors[
|
61
|
+
expect(entry.errors["base"]).to eq(["The credit and debit amounts are not equal"])
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should require the debit and credit amounts to cancel even with fractions" do
|
65
|
-
entry =
|
66
|
-
entry.credit_amounts <<
|
67
|
-
entry.debit_amounts <<
|
65
|
+
entry = FactoryBot.build(:entry)
|
66
|
+
entry.credit_amounts << FactoryBot.build(:credit_amount, amount: 100.1, entry: entry)
|
67
|
+
entry.debit_amounts << FactoryBot.build(:debit_amount, amount: 100.2, entry: entry)
|
68
68
|
expect(entry).not_to be_valid
|
69
|
-
expect(entry.errors[
|
69
|
+
expect(entry.errors["base"]).to eq(["The credit and debit amounts are not equal"])
|
70
70
|
end
|
71
71
|
|
72
72
|
it "should ignore debit and credit amounts marked for destruction to cancel" do
|
73
|
-
entry.credit_amounts <<
|
74
|
-
debit_amount =
|
73
|
+
entry.credit_amounts << FactoryBot.build(:credit_amount, amount: 100, entry: entry)
|
74
|
+
debit_amount = FactoryBot.build(:debit_amount, amount: 100, entry: entry)
|
75
75
|
debit_amount.mark_for_destruction
|
76
76
|
entry.debit_amounts << debit_amount
|
77
77
|
expect(entry).not_to be_valid
|
78
|
-
expect(entry.errors[
|
78
|
+
expect(entry.errors["base"]).to eq(["The credit and debit amounts are not equal"])
|
79
79
|
end
|
80
80
|
|
81
81
|
it "should have a polymorphic commercial document associations" do
|
82
|
-
mock_document =
|
83
|
-
entry =
|
82
|
+
mock_document = FactoryBot.create(:asset) # one would never do this, but it allows us to not require a migration for the test
|
83
|
+
entry = FactoryBot.build(:entry_with_credit_and_debit, commercial_document: mock_document)
|
84
84
|
entry.save!
|
85
85
|
saved_entry = Entry.find(entry.id)
|
86
86
|
expect(saved_entry.commercial_document).to eq(mock_document)
|
87
87
|
end
|
88
88
|
|
89
89
|
context "given a set of accounts" do
|
90
|
-
let(:mock_document) {
|
91
|
-
let!(:accounts_receivable)
|
92
|
-
|
93
|
-
|
90
|
+
let(:mock_document) { FactoryBot.create(:asset) }
|
91
|
+
let!(:accounts_receivable) do
|
92
|
+
FactoryBot.create(:asset, name: "Accounts Receivable")
|
93
|
+
end
|
94
|
+
let!(:sales_revenue) do
|
95
|
+
FactoryBot.create(:revenue, name: "Sales Revenue")
|
96
|
+
end
|
97
|
+
let!(:sales_tax_payable) do
|
98
|
+
FactoryBot.create(:liability, name: "Sales Tax Payable")
|
99
|
+
end
|
94
100
|
|
95
|
-
shared_examples_for
|
101
|
+
shared_examples_for "a built-from-hash Borutus::Entry" do
|
96
102
|
its(:credit_amounts) { is_expected.not_to be_empty }
|
97
103
|
its(:debit_amounts) { is_expected.not_to be_empty }
|
98
104
|
it { is_expected.to be_valid }
|
@@ -118,31 +124,31 @@ module Borutus
|
|
118
124
|
context "when given a credit/debits hash with :account => Account" do
|
119
125
|
let(:hash) {
|
120
126
|
{
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
127
|
+
description: "Sold some widgets",
|
128
|
+
commercial_document: mock_document,
|
129
|
+
debits: [{ account: accounts_receivable, amount: 50 }],
|
130
|
+
credits: [
|
131
|
+
{ account: sales_revenue, amount: 45 },
|
132
|
+
{ account: sales_tax_payable, amount: 5 },
|
133
|
+
],
|
128
134
|
}
|
129
135
|
}
|
130
|
-
include_examples
|
136
|
+
include_examples "a built-from-hash Borutus::Entry"
|
131
137
|
end
|
132
138
|
|
133
139
|
context "when given a credit/debits hash with :account_name => String" do
|
134
140
|
let(:hash) {
|
135
141
|
{
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
142
|
+
description: "Sold some widgets",
|
143
|
+
commercial_document: mock_document,
|
144
|
+
debits: [{ account_name: accounts_receivable.name, amount: 50 }],
|
145
|
+
credits: [
|
146
|
+
{ account_name: sales_revenue.name, amount: 45 },
|
147
|
+
{ account_name: sales_tax_payable.name, amount: 5 },
|
148
|
+
],
|
143
149
|
}
|
144
150
|
}
|
145
|
-
include_examples
|
151
|
+
include_examples "a built-from-hash Borutus::Entry"
|
146
152
|
end
|
147
153
|
end
|
148
154
|
|
@@ -154,7 +160,7 @@ module Borutus
|
|
154
160
|
after { ::ActiveSupport::Deprecation.silenced = false }
|
155
161
|
|
156
162
|
context "when used at all" do
|
157
|
-
let(:hash) {
|
163
|
+
let(:hash) { {} }
|
158
164
|
|
159
165
|
it("should be deprecated") {
|
160
166
|
# .build is the only thing deprecated
|
@@ -162,9 +168,7 @@ module Borutus
|
|
162
168
|
entry
|
163
169
|
}
|
164
170
|
end
|
165
|
-
|
166
171
|
end
|
167
172
|
end
|
168
|
-
|
169
173
|
end
|
170
174
|
end
|
data/spec/models/tenancy_spec.rb
CHANGED
@@ -10,7 +10,7 @@ module Borutus
|
|
10
10
|
Borutus.enable_tenancy = true
|
11
11
|
Borutus.tenant_class = 'Borutus::Entry'
|
12
12
|
|
13
|
-
|
13
|
+
FactoryBotHelpers.reload()
|
14
14
|
Borutus::Asset.new
|
15
15
|
end
|
16
16
|
|
@@ -23,21 +23,21 @@ module Borutus
|
|
23
23
|
Borutus.enable_tenancy = false
|
24
24
|
Borutus.tenant_class = nil
|
25
25
|
|
26
|
-
|
26
|
+
FactoryBotHelpers.reload()
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'validate uniqueness of name scoped to tenant' do
|
30
|
-
account =
|
30
|
+
account = FactoryBot.create(:asset, tenant_id: 10)
|
31
31
|
|
32
|
-
record =
|
32
|
+
record = FactoryBot.build(:asset, name: account.name, tenant_id: 10)
|
33
33
|
expect(record).not_to be_valid
|
34
34
|
expect(record.errors[:name]).to eq(['has already been taken'])
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'allows same name scoped under a different tenant' do
|
38
|
-
account =
|
38
|
+
account = FactoryBot.create(:asset, tenant_id: 10)
|
39
39
|
|
40
|
-
record =
|
40
|
+
record = FactoryBot.build(:asset, name: account.name, tenant_id: 11)
|
41
41
|
expect(record).to be_valid
|
42
42
|
end
|
43
43
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,38 +1,40 @@
|
|
1
|
-
require
|
1
|
+
require "coveralls"
|
2
2
|
Coveralls.wear!
|
3
3
|
|
4
|
-
require
|
4
|
+
require "pry"
|
5
5
|
|
6
|
-
ENV["RAILS_ENV"] ||=
|
6
|
+
ENV["RAILS_ENV"] ||= "test"
|
7
7
|
|
8
|
-
require File.expand_path(
|
9
|
-
|
8
|
+
require File.expand_path(
|
9
|
+
File.dirname(__FILE__) + "/../fixture_rails_root/config/environment",
|
10
|
+
)
|
11
|
+
require Rails.root.join("db/schema").to_s
|
10
12
|
|
11
|
-
require
|
13
|
+
require "rspec/rails"
|
12
14
|
|
13
|
-
|
15
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
14
16
|
|
15
|
-
require
|
16
|
-
require
|
17
|
+
require "borutus"
|
18
|
+
require "kaminari"
|
17
19
|
|
18
20
|
Dir[
|
19
21
|
File.expand_path(
|
20
|
-
File.join(File.dirname(__FILE__),
|
22
|
+
File.join(File.dirname(__FILE__), "support", "**", "*.rb"),
|
21
23
|
)
|
22
24
|
].each do |f|
|
23
25
|
require f
|
24
26
|
end
|
25
27
|
|
26
|
-
require
|
28
|
+
require "factory_bot"
|
27
29
|
|
28
30
|
borutus_definitions = File.expand_path(
|
29
|
-
File.join(File.dirname(__FILE__),
|
31
|
+
File.join(File.dirname(__FILE__), "factories"),
|
30
32
|
)
|
31
|
-
|
33
|
+
FactoryBot.definition_file_paths << borutus_definitions
|
32
34
|
|
33
35
|
RSpec.configure do |config|
|
34
36
|
config.use_transactional_fixtures = true
|
35
37
|
config.infer_spec_type_from_file_location!
|
36
38
|
end
|
37
39
|
|
38
|
-
|
40
|
+
FactoryBotHelpers.reload
|
@@ -1,6 +1,6 @@
|
|
1
1
|
shared_examples_for 'a Borutus::Account subtype' do |elements|
|
2
2
|
let(:contra) { false }
|
3
|
-
let(:account) {
|
3
|
+
let(:account) { FactoryBot.create(elements[:kind], contra: contra)}
|
4
4
|
subject { account }
|
5
5
|
|
6
6
|
describe "class methods" do
|
@@ -39,7 +39,7 @@ shared_examples_for 'a Borutus::Account subtype' do |elements|
|
|
39
39
|
end
|
40
40
|
|
41
41
|
describe "when given a debit" do
|
42
|
-
before {
|
42
|
+
before { FactoryBot.create(:debit_amount, account: account) }
|
43
43
|
its(:balance) { is_expected.to be.send(debit_condition, 0) }
|
44
44
|
|
45
45
|
describe "on a contra account" do
|
@@ -49,7 +49,7 @@ shared_examples_for 'a Borutus::Account subtype' do |elements|
|
|
49
49
|
end
|
50
50
|
|
51
51
|
describe "when given a credit" do
|
52
|
-
before {
|
52
|
+
before { FactoryBot.create(:credit_amount, account: account) }
|
53
53
|
its(:balance) { is_expected.to be.send(credit_condition, 0) }
|
54
54
|
|
55
55
|
describe "on a contra account" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: borutus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ramon Tayag
|
@@ -9,22 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-10-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: rails
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ">"
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '4.0'
|
21
|
-
type: :runtime
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - ">"
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: '4.0'
|
28
14
|
- !ruby/object:Gem::Dependency
|
29
15
|
name: jquery-rails
|
30
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -68,7 +54,35 @@ dependencies:
|
|
68
54
|
- !ruby/object:Gem::Version
|
69
55
|
version: '1.0'
|
70
56
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
57
|
+
name: light-service
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.11.0
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.11.0
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rails
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '4.0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '4.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: shoulda-matchers
|
72
86
|
requirement: !ruby/object:Gem::Requirement
|
73
87
|
requirements:
|
74
88
|
- - ">="
|
@@ -82,7 +96,7 @@ dependencies:
|
|
82
96
|
- !ruby/object:Gem::Version
|
83
97
|
version: '0'
|
84
98
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
99
|
+
name: yard
|
86
100
|
requirement: !ruby/object:Gem::Requirement
|
87
101
|
requirements:
|
88
102
|
- - ">="
|
@@ -95,11 +109,14 @@ dependencies:
|
|
95
109
|
- - ">="
|
96
110
|
- !ruby/object:Gem::Version
|
97
111
|
version: '0'
|
98
|
-
description:
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
112
|
+
description: |2-
|
113
|
+
|
114
|
+
The borutus plugin provides a complete double entry accounting system for
|
115
|
+
use in any Ruby on Rails application. The plugin follows general Double
|
116
|
+
Entry Bookkeeping practices. All calculations are done using BigDecimal
|
117
|
+
in order to prevent floating point rounding errors. The plugin requires
|
118
|
+
a decimal type on your database as well.
|
119
|
+
%
|
103
120
|
email:
|
104
121
|
- ramon.tayag@gmail.com
|
105
122
|
- ace.subido@gmail.com
|
@@ -134,6 +151,7 @@ files:
|
|
134
151
|
- app/models/borutus/no_tenancy.rb
|
135
152
|
- app/models/borutus/revenue.rb
|
136
153
|
- app/models/borutus/tenancy.rb
|
154
|
+
- app/services/borutus/accounts/build_running_balance_query.rb
|
137
155
|
- app/views/borutus/accounts/index.html.erb
|
138
156
|
- app/views/borutus/entries/index.html.erb
|
139
157
|
- app/views/borutus/reports/_account.html.erb
|
@@ -151,6 +169,7 @@ files:
|
|
151
169
|
- config/secret_token.rb
|
152
170
|
- config/session_store.rb
|
153
171
|
- db/migrate/20160422010135_create_borutus_tables.rb
|
172
|
+
- db/migrate/20191025095830_add_borutus_amount_counter_cache.rb
|
154
173
|
- lib/borutus.rb
|
155
174
|
- lib/borutus/engine.rb
|
156
175
|
- lib/borutus/version.rb
|
@@ -186,7 +205,7 @@ files:
|
|
186
205
|
- spec/support/account_shared_examples.rb
|
187
206
|
- spec/support/active_support_helpers.rb
|
188
207
|
- spec/support/amount_shared_examples.rb
|
189
|
-
- spec/support/
|
208
|
+
- spec/support/factory_bot_helpers.rb
|
190
209
|
- spec/support/shoulda_matchers.rb
|
191
210
|
homepage: http://github.com/bloom-solutions/borutus
|
192
211
|
licenses: []
|
@@ -237,5 +256,5 @@ test_files:
|
|
237
256
|
- spec/support/account_shared_examples.rb
|
238
257
|
- spec/support/active_support_helpers.rb
|
239
258
|
- spec/support/amount_shared_examples.rb
|
240
|
-
- spec/support/
|
259
|
+
- spec/support/factory_bot_helpers.rb
|
241
260
|
- spec/support/shoulda_matchers.rb
|