double_entry 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 05aef36c2326f83e2a5e81ef732b88eb375d40db
4
- data.tar.gz: 14e53582a9aaa42cfb5acbff3273d036d29f7c5b
3
+ metadata.gz: 614ed4f674917475306caf7d8ebbd2d71c72a5b0
4
+ data.tar.gz: ff2a94aa12cb75fa558ecab769c47a59cf40226e
5
5
  SHA512:
6
- metadata.gz: 6affae6cedb93232bd40af21f8e2d9386e90014aaed30bfa41d4bf0ff3117d16879e21afc07eaea78e5308e7ccb5ae4b12d6d7e27a7854613a3df21df39bf267
7
- data.tar.gz: 8176ff4543e6ffaad668ef63fe2862e472ebb7a160971f6d6749446ed350e334ebe309536e20e2c315b57a2849a17a21fb6a0c931ae93a0f068b40416fb63a17
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 avoid floating point rounding errors.
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 has been tested with:
20
+ DoubleEntry is tested against:
21
21
 
22
- Ruby Versions: 1.9.3, 2.0.0, 2.1.2
22
+ Ruby
23
+ * 1.9.3
24
+ * 2.1.4
23
25
 
24
- Rails Versions: Rails 3.2.x, 4.0.x, 4.1.x
26
+ Rails
27
+ * 3.2.x
28
+ * 4.1.x
25
29
 
26
- **Databases Supported:**
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
- 20.dollars,
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
 
@@ -52,7 +52,16 @@ module DoubleEntry
52
52
  end
53
53
 
54
54
  def scope_identifier
55
- ->(value) { value.is_a?(@active_record_class) ? value.id : value }
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, Symbol]
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
- if account.is_a? Symbol
57
- @account = account.to_s
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]
@@ -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
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module DoubleEntry
4
- VERSION = "0.7.0"
4
+ VERSION = "0.7.1"
5
5
  end
@@ -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) { double(:id => 1) }
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') }
@@ -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 => ->(user) { user.id })
361
- accounts.define(:identifier => :savings, :scope_identifier => ->(user) { user.id })
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 'allows you to report on scoped accounts globally' do
416
- expect(DoubleEntry.balance(:cash)).to eq ryans_cash.balance + johns_cash.balance
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.0
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-12 00:00:00.000000000 Z
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
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '../../../'
4
-
5
- gem 'rails', '~> 4.0.0'