double_entry 0.7.0 → 0.7.1
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/.travis.yml +0 -2
- data/README.md +10 -6
- data/lib/double_entry.rb +7 -0
- data/lib/double_entry/account.rb +17 -1
- data/lib/double_entry/balance_calculator.rb +3 -9
- data/lib/double_entry/errors.rb +1 -1
- data/lib/double_entry/version.rb +1 -1
- data/spec/double_entry/account_spec.rb +7 -0
- data/spec/double_entry/balance_calculator_spec.rb +1 -25
- data/spec/double_entry_spec.rb +17 -5
- metadata +2 -4
- data/spec/support/gemfiles/Gemfile.rails-4.0.x +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 614ed4f674917475306caf7d8ebbd2d71c72a5b0
|
4
|
+
data.tar.gz: ff2a94aa12cb75fa558ecab769c47a59cf40226e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c98e390fa45e02e0e117c7283964db04b6eb7d4b5c27d3de54f8d541284c40c6c557c46c47ef15d6caadb94db5341da1c4095f6adaa269675f6c5e0f100329f
|
7
|
+
data.tar.gz: da1243b2adf4f047a90250cd30ecefb49d478869dc1ed2b44bb3d0263e34ed831e8afd155bdfcf7d5c33cba077f282e1e0ac6ae28c2a20a202bda8c5131d12a2
|
data/.travis.yml
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
3
|
- 2.1.4
|
4
|
-
- 2.0.0
|
5
4
|
- 1.9.3
|
6
5
|
env:
|
7
6
|
- DB=mysql
|
@@ -16,5 +15,4 @@ script:
|
|
16
15
|
- ruby script/jack_hammer -t 2000
|
17
16
|
gemfile:
|
18
17
|
- spec/support/gemfiles/Gemfile.rails-3.2.x
|
19
|
-
- spec/support/gemfiles/Gemfile.rails-4.0.x
|
20
18
|
- spec/support/gemfiles/Gemfile.rails-4.1.x
|
data/README.md
CHANGED
@@ -13,17 +13,21 @@ DoubleEntry is an accounting system based on the principles of a
|
|
13
13
|
system. While this gem acts like a double-entry bookkeeping system, as it creates
|
14
14
|
two entries in the database for each transfer, it does *not* enforce accounting rules.
|
15
15
|
|
16
|
-
DoubleEntry uses the Money gem to
|
16
|
+
DoubleEntry uses the [Money gem](https://github.com/RubyMoney/money) to encapsulate operations on currency values.
|
17
17
|
|
18
18
|
## Compatibility
|
19
19
|
|
20
|
-
DoubleEntry
|
20
|
+
DoubleEntry is tested against:
|
21
21
|
|
22
|
-
Ruby
|
22
|
+
Ruby
|
23
|
+
* 1.9.3
|
24
|
+
* 2.1.4
|
23
25
|
|
24
|
-
Rails
|
26
|
+
Rails
|
27
|
+
* 3.2.x
|
28
|
+
* 4.1.x
|
25
29
|
|
26
|
-
|
30
|
+
Databases
|
27
31
|
* MySQL
|
28
32
|
* PostgreSQL
|
29
33
|
* SQLite
|
@@ -104,7 +108,7 @@ To transfer money between accounts:
|
|
104
108
|
|
105
109
|
```ruby
|
106
110
|
DoubleEntry.transfer(
|
107
|
-
|
111
|
+
Money.new(20_00),
|
108
112
|
:from => one_account,
|
109
113
|
:to => another_account,
|
110
114
|
:code => :a_business_code_for_this_type_of_transfer,
|
data/lib/double_entry.rb
CHANGED
@@ -37,6 +37,8 @@ module DoubleEntry
|
|
37
37
|
# @return [DoubleEntry::Account::Instance]
|
38
38
|
# @raise [DoubleEntry::UnknownAccount] The described account has not been
|
39
39
|
# configured. It is unknown.
|
40
|
+
# @raise [DoubleEntry::AccountScopeMismatchError] The provided scope does not
|
41
|
+
# match that defined on the account.
|
40
42
|
#
|
41
43
|
def account(identifier, options = {})
|
42
44
|
Account.account(configuration.accounts, identifier, options)
|
@@ -124,7 +126,12 @@ module DoubleEntry
|
|
124
126
|
# @option options :codes [Array<Symbol>] consider only the transfers with
|
125
127
|
# these codes
|
126
128
|
# @return [Money] The balance
|
129
|
+
# @raise [DoubleEntry::UnknownAccount] The described account has not been
|
130
|
+
# configured. It is unknown.
|
131
|
+
# @raise [DoubleEntry::AccountScopeMismatchError] The provided scope does not
|
132
|
+
# match that defined on the account.
|
127
133
|
def balance(account, options = {})
|
134
|
+
account = account(account, options) if account.is_a? Symbol
|
128
135
|
BalanceCalculator.calculate(account, options)
|
129
136
|
end
|
130
137
|
|
data/lib/double_entry/account.rb
CHANGED
@@ -52,7 +52,16 @@ module DoubleEntry
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def scope_identifier
|
55
|
-
|
55
|
+
lambda do |value|
|
56
|
+
case value
|
57
|
+
when @active_record_class
|
58
|
+
value.id
|
59
|
+
when String, Fixnum
|
60
|
+
value
|
61
|
+
else
|
62
|
+
raise AccountScopeMismatchError.new("Expected instance of `#{@active_record_class}`, received instance of `#{value.class}`")
|
63
|
+
end
|
64
|
+
end
|
56
65
|
end
|
57
66
|
end
|
58
67
|
|
@@ -62,6 +71,7 @@ module DoubleEntry
|
|
62
71
|
|
63
72
|
def initialize(attributes)
|
64
73
|
attributes.each { |name, value| send("#{name}=", value) }
|
74
|
+
ensure_scope_is_valid
|
65
75
|
end
|
66
76
|
|
67
77
|
def scope_identity
|
@@ -110,6 +120,12 @@ module DoubleEntry
|
|
110
120
|
def inspect
|
111
121
|
to_s
|
112
122
|
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def ensure_scope_is_valid
|
127
|
+
scope_identity
|
128
|
+
end
|
113
129
|
end
|
114
130
|
|
115
131
|
attr_accessor :identifier, :scope_identifier, :positive_only, :currency
|
@@ -5,8 +5,7 @@ module DoubleEntry
|
|
5
5
|
|
6
6
|
# Get the current or historic balance of an account.
|
7
7
|
#
|
8
|
-
# @param account [DoubleEntry::Account:Instance
|
9
|
-
# @option args :scope [Object, String]
|
8
|
+
# @param account [DoubleEntry::Account:Instance]
|
10
9
|
# @option args :from [Time]
|
11
10
|
# @option args :to [Time]
|
12
11
|
# @option args :at [Time]
|
@@ -53,13 +52,8 @@ module DoubleEntry
|
|
53
52
|
attr_reader :account, :scope, :from, :to, :at, :codes
|
54
53
|
|
55
54
|
def initialize(account, args = {})
|
56
|
-
|
57
|
-
|
58
|
-
@scope = args[:scope].present? ? args[:scope].id.to_s : nil
|
59
|
-
else
|
60
|
-
@account = account.identifier.to_s
|
61
|
-
@scope = account.scope_identity
|
62
|
-
end
|
55
|
+
@account = account.identifier.to_s
|
56
|
+
@scope = account.scope_identity
|
63
57
|
@codes = (args[:codes].to_a << args[:code]).compact
|
64
58
|
@from = args[:from]
|
65
59
|
@to = args[:to]
|
data/lib/double_entry/errors.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module DoubleEntry
|
3
|
-
|
4
3
|
class UnknownAccount < RuntimeError; end
|
5
4
|
class TransferNotAllowed < RuntimeError; end
|
6
5
|
class TransferIsNegative < RuntimeError; end
|
@@ -9,4 +8,5 @@ module DoubleEntry
|
|
9
8
|
class AccountWouldBeSentNegative < RuntimeError; end
|
10
9
|
class MismatchedCurrencies < RuntimeError; end
|
11
10
|
class MissingAccountError < RuntimeError; end;
|
11
|
+
class AccountScopeMismatchError < RuntimeError; end;
|
12
12
|
end
|
data/lib/double_entry/version.rb
CHANGED
@@ -73,6 +73,13 @@ module DoubleEntry
|
|
73
73
|
it { should eq 32 }
|
74
74
|
end
|
75
75
|
|
76
|
+
context "given differing model instance with ID 32" do
|
77
|
+
let(:value) { double(:id => 32) }
|
78
|
+
it "raises an error" do
|
79
|
+
expect { scope_identifier.call(value) }.to raise_error DoubleEntry::AccountScopeMismatchError
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
76
83
|
context "given the String 'I am a bearded lady'" do
|
77
84
|
let(:value) { "I am a bearded lady" }
|
78
85
|
|
@@ -5,7 +5,7 @@ describe DoubleEntry::BalanceCalculator do
|
|
5
5
|
|
6
6
|
describe '#calculate' do
|
7
7
|
let(:account) { DoubleEntry::account(:test, :scope => scope) }
|
8
|
-
let(:scope) {
|
8
|
+
let(:scope) { User.make! }
|
9
9
|
let(:from) { nil }
|
10
10
|
let(:to) { nil }
|
11
11
|
let(:at) { nil }
|
@@ -26,30 +26,6 @@ describe DoubleEntry::BalanceCalculator do
|
|
26
26
|
)
|
27
27
|
end
|
28
28
|
|
29
|
-
describe 'what happens with different accounts' do
|
30
|
-
context 'when the given account is a symbol' do
|
31
|
-
let(:account) { :test }
|
32
|
-
|
33
|
-
it 'scopes the lines summed by the account symbol' do
|
34
|
-
expect(DoubleEntry::Line).to have_received(:where).with(:account => 'test')
|
35
|
-
end
|
36
|
-
|
37
|
-
context 'with a scopeable entity provided' do
|
38
|
-
let(:scope) { double(:id => 'scope') }
|
39
|
-
|
40
|
-
it 'scopes the lines summed by the scope of the scopeable entity...scope' do
|
41
|
-
expect(relation).to have_received(:where).with(:scope => 'scope')
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'with no scope provided' do
|
46
|
-
it 'does not scope the lines summed by the given scope' do
|
47
|
-
expect(relation).to_not have_received(:where).with(:scope => 'scope')
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
29
|
describe 'what happens with different times' do
|
54
30
|
context 'when we want to sum the lines before a given created_at date' do
|
55
31
|
let(:at) { Time.parse('2014-06-19 15:09:18 +1000') }
|
data/spec/double_entry_spec.rb
CHANGED
@@ -356,9 +356,10 @@ describe DoubleEntry do
|
|
356
356
|
before do
|
357
357
|
DoubleEntry.configure do |config|
|
358
358
|
config.define_accounts do |accounts|
|
359
|
+
user_scope = accounts.active_record_scope_identifier(User)
|
359
360
|
accounts.define(:identifier => :bank)
|
360
|
-
accounts.define(:identifier => :cash, :scope_identifier =>
|
361
|
-
accounts.define(:identifier => :savings, :scope_identifier =>
|
361
|
+
accounts.define(:identifier => :cash, :scope_identifier => user_scope)
|
362
|
+
accounts.define(:identifier => :savings, :scope_identifier => user_scope)
|
362
363
|
end
|
363
364
|
|
364
365
|
config.define_transfers do |transfers|
|
@@ -400,6 +401,18 @@ describe DoubleEntry do
|
|
400
401
|
expect(DoubleEntry.balance(:cash, :scope => ryan)).to eq -Money.new(10_00)
|
401
402
|
end
|
402
403
|
|
404
|
+
it 'raises an exception if you try to scope with an object instance of differing class to that defined on the account' do
|
405
|
+
not_a_user = double(:id => 7)
|
406
|
+
|
407
|
+
expect {
|
408
|
+
DoubleEntry.account(:savings, :scope => not_a_user)
|
409
|
+
}.to raise_error DoubleEntry::AccountScopeMismatchError
|
410
|
+
|
411
|
+
expect {
|
412
|
+
DoubleEntry.balance(:savings, :scope => not_a_user)
|
413
|
+
}.to raise_error DoubleEntry::AccountScopeMismatchError
|
414
|
+
end
|
415
|
+
|
403
416
|
it 'raises exception if you try to transfer between the same account, despite it being scoped' do
|
404
417
|
expect do
|
405
418
|
DoubleEntry.transfer(Money.new(10_00), :from => ryans_cash, :to => ryans_cash, :code => :xfer)
|
@@ -412,9 +425,8 @@ describe DoubleEntry do
|
|
412
425
|
expect(ryans_savings.balance).to eq Money.new(100_00)
|
413
426
|
end
|
414
427
|
|
415
|
-
it '
|
416
|
-
expect
|
417
|
-
expect(DoubleEntry.balance(:savings)).to eq ryans_savings.balance + johns_savings.balance
|
428
|
+
it 'disallows you to report on scoped accounts globally' do
|
429
|
+
expect { DoubleEntry.balance(:cash) }.to raise_error DoubleEntry::UnknownAccount
|
418
430
|
end
|
419
431
|
end
|
420
432
|
end
|
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.7.
|
4
|
+
version: 0.7.1
|
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: 2014-11-
|
18
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: money
|
@@ -291,7 +291,6 @@ files:
|
|
291
291
|
- spec/support/database.travis.yml
|
292
292
|
- spec/support/double_entry_spec_helper.rb
|
293
293
|
- spec/support/gemfiles/Gemfile.rails-3.2.x
|
294
|
-
- spec/support/gemfiles/Gemfile.rails-4.0.x
|
295
294
|
- spec/support/gemfiles/Gemfile.rails-4.1.x
|
296
295
|
- spec/support/reporting_configuration.rb
|
297
296
|
- spec/support/schema.rb
|
@@ -345,7 +344,6 @@ test_files:
|
|
345
344
|
- spec/support/database.travis.yml
|
346
345
|
- spec/support/double_entry_spec_helper.rb
|
347
346
|
- spec/support/gemfiles/Gemfile.rails-3.2.x
|
348
|
-
- spec/support/gemfiles/Gemfile.rails-4.0.x
|
349
347
|
- spec/support/gemfiles/Gemfile.rails-4.1.x
|
350
348
|
- spec/support/reporting_configuration.rb
|
351
349
|
- spec/support/schema.rb
|