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 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'