double_entry 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +26 -19
  3. data/.travis.yml +4 -4
  4. data/Gemfile +0 -1
  5. data/README.md +16 -3
  6. data/double_entry.gemspec +4 -5
  7. data/lib/active_record/locking_extensions.rb +1 -1
  8. data/lib/double_entry.rb +8 -1
  9. data/lib/double_entry/account.rb +15 -3
  10. data/lib/double_entry/account_balance.rb +13 -3
  11. data/lib/double_entry/balance_calculator.rb +3 -2
  12. data/lib/double_entry/errors.rb +2 -1
  13. data/lib/double_entry/line.rb +31 -12
  14. data/lib/double_entry/locking.rb +0 -1
  15. data/lib/double_entry/reporting/aggregate.rb +9 -5
  16. data/lib/double_entry/reporting/aggregate_array.rb +5 -1
  17. data/lib/double_entry/reporting/line_aggregate.rb +0 -1
  18. data/lib/double_entry/transfer.rb +5 -3
  19. data/lib/double_entry/validation/line_check.rb +3 -3
  20. data/lib/double_entry/version.rb +1 -1
  21. data/lib/generators/double_entry/install/templates/migration.rb +1 -1
  22. data/spec/double_entry/account_spec.rb +12 -0
  23. data/spec/double_entry/balance_calculator_spec.rb +4 -21
  24. data/spec/double_entry/line_spec.rb +49 -38
  25. data/spec/double_entry/locking_spec.rb +2 -2
  26. data/spec/double_entry/reporting/aggregate_array_spec.rb +18 -3
  27. data/spec/double_entry/reporting/aggregate_spec.rb +13 -0
  28. data/spec/double_entry/validation/line_check_spec.rb +16 -0
  29. data/spec/double_entry_spec.rb +40 -10
  30. data/spec/spec_helper.rb +14 -8
  31. data/spec/support/accounts.rb +9 -5
  32. data/spec/support/blueprints.rb +9 -0
  33. data/spec/support/database.example.yml +1 -1
  34. data/spec/support/database.travis.yml +1 -1
  35. data/spec/support/double_entry_spec_helper.rb +8 -0
  36. data/{gemfiles/Gemfile.rails-3.2.0 → spec/support/gemfiles/Gemfile.rails-3.2.x} +2 -2
  37. data/spec/support/gemfiles/Gemfile.rails-4.0.x +5 -0
  38. data/spec/support/gemfiles/Gemfile.rails-4.1.x +5 -0
  39. metadata +16 -28
  40. data/db/.gitkeep +0 -0
  41. data/gemfiles/Gemfile.rails-4.0.0 +0 -5
  42. data/gemfiles/Gemfile.rails-4.1.0 +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 872b6fa2ec70dd3783192e17d4f79139a288d859
4
- data.tar.gz: 9b116b6617a97740ba998b8efc26fdc2a51d38e8
3
+ metadata.gz: 05aef36c2326f83e2a5e81ef732b88eb375d40db
4
+ data.tar.gz: 14e53582a9aaa42cfb5acbff3273d036d29f7c5b
5
5
  SHA512:
6
- metadata.gz: dc9648ffc3737e9b8aa9b3ceb7b8fb831dd034c04eb3e9ac756c08ecf4932fe9cca416a792339d9d2dd8036aef70439ed6200b147ee513cdcd30bdfa44ea7e37
7
- data.tar.gz: 3aa8185c00db1211e6c537a063a5b345372e98cc05987f86e54bea75f423fbd5d917685064651951bd7f6b4aa42fbdaf6088a238b83f275fcce1de551325f373
6
+ metadata.gz: 6affae6cedb93232bd40af21f8e2d9386e90014aaed30bfa41d4bf0ff3117d16879e21afc07eaea78e5308e7ccb5ae4b12d6d7e27a7854613a3df21df39bf267
7
+ data.tar.gz: 8176ff4543e6ffaad668ef63fe2862e472ebb7a160971f6d6749446ed350e334ebe309536e20e2c315b57a2849a17a21fb6a0c931ae93a0f068b40416fb63a17
data/.gitignore CHANGED
@@ -1,22 +1,29 @@
1
1
  *.gem
2
2
  *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- .ruby-version
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- spec/support/database.yml
16
- test/tmp
17
- test/version_tmp
18
- tmp
19
- db/*.sqlite3
20
- bin/
21
- log/
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Documentation cache and generated files:
13
+ /.yardoc/
14
+ /_yardoc/
15
+ /doc/
16
+ /rdoc/
17
+
18
+ ## Environment normalisation:
19
+ /.bundle/
20
+ /lib/bundler/man/
22
21
  /Gemfile.lock
22
+ /.ruby-version
23
+ /.ruby-gemset
24
+
25
+ # DoubleEntry specific
26
+ /bin/
27
+ /log/
28
+ /spec/reports/
29
+ /spec/support/database.yml
data/.travis.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.2
3
+ - 2.1.4
4
4
  - 2.0.0
5
5
  - 1.9.3
6
6
  env:
@@ -15,6 +15,6 @@ script:
15
15
  - rake spec
16
16
  - ruby script/jack_hammer -t 2000
17
17
  gemfile:
18
- - gemfiles/Gemfile.rails-3.2.0
19
- - gemfiles/Gemfile.rails-4.0.0
20
- - gemfiles/Gemfile.rails-4.1.0
18
+ - spec/support/gemfiles/Gemfile.rails-3.2.x
19
+ - spec/support/gemfiles/Gemfile.rails-4.0.x
20
+ - spec/support/gemfiles/Gemfile.rails-4.1.x
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
2
  gemspec
data/README.md CHANGED
@@ -26,6 +26,7 @@ Rails Versions: Rails 3.2.x, 4.0.x, 4.1.x
26
26
  **Databases Supported:**
27
27
  * MySQL
28
28
  * PostgreSQL
29
+ * SQLite
29
30
 
30
31
  ## Installation
31
32
 
@@ -124,7 +125,7 @@ manually lock the accounts you're using:
124
125
  ```ruby
125
126
  DoubleEntry.lock_accounts(account_a, account_b) do
126
127
  # Perhaps transfer some money
127
- DoubleEntry.transfer(20.dollars, :from => account_a, :to => account_b, :code => :purchase)
128
+ DoubleEntry.transfer(Money.new(20_00), :from => account_a, :to => account_b, :code => :purchase)
128
129
  # Perform other tasks that should be commited atomically with the transfer of funds...
129
130
  end
130
131
  ```
@@ -181,6 +182,19 @@ DoubleEntry.configure do |config|
181
182
  end
182
183
  ```
183
184
 
185
+ By default an account's currency is the same as Money.default_currency from the money gem.
186
+
187
+ You can also specify a currency on a per account basis.
188
+ Transfers between accounts of different currencies are not allowed.
189
+
190
+ ```ruby
191
+ DoubleEntry.configure do |config|
192
+ config.define_accounts do |accounts|
193
+ accounts.define(:identifier => :savings, :scope_identifier => user_scope, :currency => :aud)
194
+ end
195
+ end
196
+ ```
197
+
184
198
  ## Jackhammer
185
199
 
186
200
  Run a concurrency test on the code.
@@ -240,7 +254,7 @@ See the Github project [issues](https://github.com/envato/double_entry/issues).
240
254
  ./script/setup.sh
241
255
  ```
242
256
 
243
- 3. Install MySQL and PostgreSQL. We run tests against both databases.
257
+ 3. Install MySQL, PostgreSQL and SQLite. We run tests against all three databases.
244
258
  4. Create a database in MySQL.
245
259
 
246
260
  ```sh
@@ -265,4 +279,3 @@ See the Github project [issues](https://github.com/envato/double_entry/issues).
265
279
  ```sh
266
280
  bundle exec rake
267
281
  ```
268
-
data/double_entry.gemspec CHANGED
@@ -19,11 +19,10 @@ Gem::Specification.new do |gem|
19
19
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
20
  gem.require_paths = ['lib']
21
21
 
22
- gem.add_dependency 'money', '>= 5.1.0'
23
- gem.add_dependency 'encapsulate_as_money'
24
- gem.add_dependency 'activerecord', '>= 3.2.9'
25
- gem.add_dependency 'activesupport', '>= 3.0.0'
26
- gem.add_dependency 'railties', '>= 3.0.0'
22
+ gem.add_dependency 'money', '>= 6.0.0'
23
+ gem.add_dependency 'activerecord', '>= 3.2.0'
24
+ gem.add_dependency 'activesupport', '>= 3.2.0'
25
+ gem.add_dependency 'railties', '>= 3.2.0'
27
26
 
28
27
  gem.add_development_dependency 'rake'
29
28
  gem.add_development_dependency 'mysql2'
@@ -48,7 +48,7 @@ module ActiveRecord
48
48
  begin
49
49
  yield
50
50
  rescue ActiveRecord::StatementInvalid, ActiveRecord::RecordNotUnique => exception
51
- if exception.message =~ /duplicate/i || exception.message =~ /(is|are) not unique/i
51
+ if exception.message =~ /duplicate/i || exception.message =~ /ConstraintException/
52
52
  # Just ignore it...someone else has already created the record.
53
53
  else
54
54
  raise
data/lib/double_entry.rb CHANGED
@@ -3,7 +3,6 @@ require 'active_record'
3
3
  require 'active_record/locking_extensions'
4
4
  require 'active_support/all'
5
5
  require 'money'
6
- require 'encapsulate_as_money'
7
6
 
8
7
  require 'double_entry/version'
9
8
  require 'double_entry/errors'
@@ -129,6 +128,14 @@ module DoubleEntry
129
128
  BalanceCalculator.calculate(account, options)
130
129
  end
131
130
 
131
+ # Get the currency of an account.
132
+ #
133
+ # @param [DoubleEntry::Account:Instance, Symbol] account Find the currency for this account
134
+ # @return [Currency] the currency
135
+ def currency(account)
136
+ Account.currency(configuration.accounts, account)
137
+ end
138
+
132
139
  # Lock accounts in preparation for transfers.
133
140
  #
134
141
  # This creates a transaction, and uses database-level locking to ensure
@@ -8,6 +8,17 @@ module DoubleEntry
8
8
  DoubleEntry::Account::Instance.new(:account => account, :scope => options[:scope])
9
9
  end
10
10
 
11
+ # @api private
12
+ def self.currency(defined_accounts, account)
13
+ code = account.is_a?(Symbol) ? account : account.identifier
14
+
15
+ found_account = defined_accounts.detect do |account|
16
+ account.identifier == code
17
+ end
18
+
19
+ found_account.currency
20
+ end
21
+
11
22
  # @api private
12
23
  class Set < Array
13
24
  def define(attributes)
@@ -47,7 +58,7 @@ module DoubleEntry
47
58
 
48
59
  class Instance
49
60
  attr_accessor :account, :scope
50
- delegate :identifier, :scope_identifier, :scoped?, :positive_only, :to => :account
61
+ delegate :identifier, :scope_identifier, :scoped?, :positive_only, :currency, :to => :account
51
62
 
52
63
  def initialize(attributes)
53
64
  attributes.each { |name, value| send("#{name}=", value) }
@@ -93,7 +104,7 @@ module DoubleEntry
93
104
  end
94
105
 
95
106
  def to_s
96
- "\#{Account account: #{identifier} scope: #{scope}}"
107
+ "\#{Account account: #{identifier} scope: #{scope} currency: #{currency}}"
97
108
  end
98
109
 
99
110
  def inspect
@@ -101,10 +112,11 @@ module DoubleEntry
101
112
  end
102
113
  end
103
114
 
104
- attr_accessor :identifier, :scope_identifier, :positive_only
115
+ attr_accessor :identifier, :scope_identifier, :positive_only, :currency
105
116
 
106
117
  def initialize(attributes)
107
118
  attributes.each { |name, value| send("#{name}=", value) }
119
+ self.currency ||= Money.default_currency
108
120
  end
109
121
 
110
122
  def scoped?
@@ -9,9 +9,16 @@ module DoubleEntry
9
9
  #
10
10
  # Account balances are created on demand when transfers occur.
11
11
  class AccountBalance < ActiveRecord::Base
12
- extend EncapsulateAsMoney
13
12
 
14
- encapsulate_as_money :balance
13
+ delegate :currency, :to => :account
14
+
15
+ def balance
16
+ self[:balance] && Money.new(self[:balance], currency)
17
+ end
18
+
19
+ def balance=(money)
20
+ self[:balance] = (money && money.fractional)
21
+ end
15
22
 
16
23
  def account=(account)
17
24
  self[:account] = account.identifier.to_s
@@ -19,6 +26,10 @@ module DoubleEntry
19
26
  account
20
27
  end
21
28
 
29
+ def account
30
+ DoubleEntry.account(self[:account].to_sym, :scope => self[:scope])
31
+ end
32
+
22
33
  def self.find_by_account(account, options = {})
23
34
  scope = where(:scope => account.scope_identity, :account => account.identifier.to_s)
24
35
  scope = scope.lock(true) if options[:lock]
@@ -28,4 +39,3 @@ module DoubleEntry
28
39
  end
29
40
 
30
41
  end
31
-
@@ -18,10 +18,11 @@ module DoubleEntry
18
18
  options = Options.new(account, args)
19
19
  relations = RelationBuilder.new(options)
20
20
  lines = relations.build
21
+ currency = DoubleEntry.currency(account)
21
22
 
22
23
  if options.between? || options.code?
23
24
  # from and to or code lookups have to be done via sum
24
- Money.new(lines.sum(:amount))
25
+ Money.new(lines.sum(:amount), currency)
25
26
  else
26
27
  # all other lookups can be performed with running balances
27
28
  result = lines.
@@ -29,7 +30,7 @@ module DoubleEntry
29
30
  order('id DESC').
30
31
  limit(1).
31
32
  pluck(:balance)
32
- result.empty? ? Money.empty : Money.new(result.first)
33
+ result.empty? ? Money.zero(currency) : Money.new(result.first, currency)
33
34
  end
34
35
  end
35
36
 
@@ -7,5 +7,6 @@ module DoubleEntry
7
7
  class DuplicateAccount < RuntimeError; end
8
8
  class DuplicateTransfer < RuntimeError; end
9
9
  class AccountWouldBeSentNegative < RuntimeError; end
10
-
10
+ class MismatchedCurrencies < RuntimeError; end
11
+ class MissingAccountError < RuntimeError; end;
11
12
  end
@@ -56,11 +56,24 @@ module DoubleEntry
56
56
  # by account, or account and code, over a particular period.
57
57
  #
58
58
  class Line < ActiveRecord::Base
59
- extend EncapsulateAsMoney
60
59
 
61
60
  belongs_to :detail, :polymorphic => true
62
61
 
63
- encapsulate_as_money :amount, :balance
62
+ def amount
63
+ self[:amount] && Money.new(self[:amount], currency)
64
+ end
65
+
66
+ def amount=(money)
67
+ self[:amount] = (money && money.fractional)
68
+ end
69
+
70
+ def balance
71
+ self[:balance] && Money.new(self[:balance], currency)
72
+ end
73
+
74
+ def balance=(money)
75
+ self[:balance] = (money && money.fractional)
76
+ end
64
77
 
65
78
  def save(*)
66
79
  check_balance_will_not_be_sent_negative
@@ -81,20 +94,26 @@ module DoubleEntry
81
94
  self[:code].try(:to_sym)
82
95
  end
83
96
 
84
- def account=(account)
85
- self[:account] = account.identifier.to_s
86
- self.scope = account.scope_identity
87
- account
97
+ def account=(_account)
98
+ self[:account] = _account.identifier.to_s
99
+ self.scope = _account.scope_identity
100
+ raise "Missing Account" unless account
101
+ _account
88
102
  end
89
103
 
90
104
  def account
91
105
  DoubleEntry.account(self[:account].to_sym, :scope => scope)
92
106
  end
93
107
 
94
- def partner_account=(partner_account)
95
- self[:partner_account] = partner_account.identifier.to_s
96
- self.partner_scope = partner_account.scope_identity
97
- partner_account
108
+ def currency
109
+ account.currency if self[:account]
110
+ end
111
+
112
+ def partner_account=(_partner_account)
113
+ self[:partner_account] = _partner_account.identifier.to_s
114
+ self.partner_scope = _partner_account.scope_identity
115
+ raise "Missing Partner Account" unless partner_account
116
+ _partner_account
98
117
  end
99
118
 
100
119
  def partner_account
@@ -114,11 +133,11 @@ module DoubleEntry
114
133
  end
115
134
 
116
135
  def decrease?
117
- amount < Money.empty
136
+ amount < Money.zero
118
137
  end
119
138
 
120
139
  def increase?
121
- amount > Money.empty
140
+ amount > Money.zero
122
141
  end
123
142
 
124
143
  # Query out just the id and created_at fields for lines, without
@@ -162,7 +162,6 @@ module DoubleEntry
162
162
  @accounts_without_balances.each do |account|
163
163
  # Get the initial balance from the lines table.
164
164
  balance = account.balance
165
-
166
165
  # Try to create the balance record, but ignore it if someone else has done it in the meantime.
167
166
  AccountBalance.create_ignoring_duplicates!(:account => account, :balance => balance)
168
167
  end
@@ -8,7 +8,7 @@ module DoubleEntry
8
8
  @function = function.to_s
9
9
  raise AggregateFunctionNotSupported unless %w[sum count average].include?(@function)
10
10
 
11
- @account = account.to_s
11
+ @account = account
12
12
  @code = code ? code.to_s : nil
13
13
  @options = options
14
14
  @range = options[:range]
@@ -25,17 +25,17 @@ module DoubleEntry
25
25
  end
26
26
 
27
27
  def formatted_amount
28
- Aggregate.formatted_amount(function, amount)
28
+ Aggregate.formatted_amount(function, amount, currency)
29
29
  end
30
30
 
31
- def self.formatted_amount(function, amount)
31
+ def self.formatted_amount(function, amount, currency)
32
32
  safe_amount = amount || 0
33
33
 
34
34
  case function.to_s
35
35
  when 'count'
36
36
  safe_amount
37
37
  else
38
- Money.new(safe_amount)
38
+ Money.new(safe_amount, currency)
39
39
  end
40
40
  end
41
41
 
@@ -46,6 +46,10 @@ module DoubleEntry
46
46
  aggregate.amount if aggregate
47
47
  end
48
48
 
49
+ def currency
50
+ DoubleEntry.currency(account)
51
+ end
52
+
49
53
  def clear_old_aggregates
50
54
  LineAggregate.delete_all(field_hash)
51
55
  end
@@ -75,7 +79,7 @@ module DoubleEntry
75
79
  when 'average'
76
80
  calculate_yearly_average
77
81
  else
78
- zero = Aggregate.formatted_amount(function, 0)
82
+ zero = Aggregate.formatted_amount(function, 0, currency)
79
83
 
80
84
  result = (1..12).inject(zero) do |total, month|
81
85
  total += Reporting.aggregate(function, account, code,
@@ -54,7 +54,7 @@ module DoubleEntry
54
54
  where(:filter => filter.inspect).
55
55
  where(LineAggregate.arel_table[range_type].not_eq(nil)).
56
56
  inject({}) do |hash, result|
57
- hash[result.key] = Aggregate.formatted_amount(function, result.amount)
57
+ hash[result.key] = Aggregate.formatted_amount(function, result.amount, currency)
58
58
  hash
59
59
  end
60
60
  end
@@ -62,6 +62,10 @@ module DoubleEntry
62
62
  def all_periods
63
63
  TimeRangeArray.make(range_type, start, finish)
64
64
  end
65
+
66
+ def currency
67
+ DoubleEntry.currency(account)
68
+ end
65
69
  end
66
70
  end
67
71
  end
@@ -2,7 +2,6 @@
2
2
  module DoubleEntry
3
3
  module Reporting
4
4
  class LineAggregate < ActiveRecord::Base
5
- extend EncapsulateAsMoney
6
5
 
7
6
  def self.aggregate(function, account, code, range, named_scopes)
8
7
  collection = aggregate_collection(named_scopes)
@@ -4,7 +4,7 @@ module DoubleEntry
4
4
 
5
5
  # @api private
6
6
  def self.transfer(defined_transfers, amount, options = {})
7
- raise TransferIsNegative if amount < Money.empty
7
+ raise TransferIsNegative if amount < Money.zero
8
8
  from, to, code, detail = options[:from], options[:to], options[:code], options[:detail]
9
9
  defined_transfers.
10
10
  find!(from, to, code).
@@ -52,9 +52,11 @@ module DoubleEntry
52
52
 
53
53
  def process(amount, from, to, code, detail)
54
54
  if from.scope_identity == to.scope_identity and from.identifier == to.identifier
55
- raise TransferNotAllowed.new
55
+ raise TransferNotAllowed.new("from and to are identical")
56
+ end
57
+ if to.currency != from.currency
58
+ raise MismatchedCurrencies.new("Missmatched currency (#{to.currency} <> #{from.currency})")
56
59
  end
57
-
58
60
  Locking.lock_accounts(from, to) do
59
61
  credit, debit = Line.new, Line.new
60
62
 
@@ -4,7 +4,6 @@ require 'set'
4
4
  module DoubleEntry
5
5
  module Validation
6
6
  class LineCheck < ActiveRecord::Base
7
- extend EncapsulateAsMoney
8
7
 
9
8
  default_scope -> { order('created_at') }
10
9
 
@@ -65,7 +64,8 @@ module DoubleEntry
65
64
  # yes, it needs to be find_by_sql, because any other find will be affected
66
65
  # by the find_each call in perform!
67
66
  previous_line = Line.find_by_sql(["SELECT * FROM #{Line.quoted_table_name} #{force_index} WHERE account = ? AND scope = ? AND id < ? ORDER BY id DESC LIMIT 1", line.account.identifier.to_s, line.scope, line.id])
68
- previous_balance = previous_line.length == 1 ? previous_line[0].balance : Money.empty
67
+
68
+ previous_balance = previous_line.length == 1 ? previous_line[0].balance : Money.zero(line.account.currency)
69
69
 
70
70
  if line.balance != (line.amount + previous_balance)
71
71
  log << line_error_message(line, previous_line, previous_balance)
@@ -93,7 +93,7 @@ module DoubleEntry
93
93
 
94
94
  def recalculate_account(account)
95
95
  DoubleEntry.lock_accounts(account) do
96
- recalculated_balance = Money.empty
96
+ recalculated_balance = Money.zero(account.currency)
97
97
 
98
98
  lines_for_account(account).each do |line|
99
99
  recalculated_balance += line.amount
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module DoubleEntry
4
- VERSION = "0.6.1"
4
+ VERSION = "0.7.0"
5
5
  end
@@ -41,9 +41,9 @@ class CreateDoubleEntryTables < ActiveRecord::Migration
41
41
  t.integer "day"
42
42
  t.integer "hour"
43
43
  t.integer "amount"
44
- t.timestamps
45
44
  t.string "filter"
46
45
  t.string "range_type"
46
+ t.timestamps
47
47
  end
48
48
 
49
49
  add_index "double_entry_line_aggregates", ["function", "account", "code", "year", "month", "week", "day"], :name => "line_aggregate_idx"
@@ -20,6 +20,18 @@ module DoubleEntry
20
20
  expect(a1.hash).to eq a2.hash
21
21
  expect(a1.hash).to_not eq b.hash
22
22
  end
23
+
24
+ describe "currency" do
25
+ it "defaults to USD currency" do
26
+ account = DoubleEntry::Account.new(:identifier => "savings", :scope_identifier => identity_scope)
27
+ expect(DoubleEntry::Account::Instance.new(:account => account).currency).to eq("USD")
28
+ end
29
+
30
+ it "allows the currency to be set" do
31
+ account = DoubleEntry::Account.new(:identifier => "savings", :scope_identifier => identity_scope, :currency => "AUD")
32
+ expect(DoubleEntry::Account::Instance.new(:account => account).currency).to eq("AUD")
33
+ end
34
+ end
23
35
  end
24
36
 
25
37
  describe Account::Set do
@@ -4,8 +4,8 @@ require 'spec_helper'
4
4
  describe DoubleEntry::BalanceCalculator do
5
5
 
6
6
  describe '#calculate' do
7
- let(:account) { double.as_null_object }
8
- let(:scope) { nil }
7
+ let(:account) { DoubleEntry::account(:test, :scope => scope) }
8
+ let(:scope) { double(:id => 1) }
9
9
  let(:from) { nil }
10
10
  let(:to) { nil }
11
11
  let(:at) { nil }
@@ -28,10 +28,10 @@ describe DoubleEntry::BalanceCalculator do
28
28
 
29
29
  describe 'what happens with different accounts' do
30
30
  context 'when the given account is a symbol' do
31
- let(:account) { :account }
31
+ let(:account) { :test }
32
32
 
33
33
  it 'scopes the lines summed by the account symbol' do
34
- expect(DoubleEntry::Line).to have_received(:where).with(:account => 'account')
34
+ expect(DoubleEntry::Line).to have_received(:where).with(:account => 'test')
35
35
  end
36
36
 
37
37
  context 'with a scopeable entity provided' do
@@ -48,23 +48,6 @@ describe DoubleEntry::BalanceCalculator do
48
48
  end
49
49
  end
50
50
  end
51
-
52
- context 'when the given account is DoubleEntry::Account-like' do
53
- let(:account) do
54
- DoubleEntry::Account::Instance.new(
55
- :account => DoubleEntry::Account.new(
56
- :identifier => 'account_identity',
57
- :scope_identifier => lambda { |scope_id| scope_id },
58
- ),
59
- :scope => 'account_scope_identity'
60
- )
61
- end
62
-
63
- it 'scopes the lines summed by the accounts identifier and its scope identity' do
64
- expect(DoubleEntry::Line).to have_received(:where).with(:account => 'account_identity')
65
- expect(relation).to have_received(:where).with(:scope => 'account_scope_identity')
66
- end
67
- end
68
51
  end
69
52
 
70
53
  describe 'what happens with different times' do
@@ -1,12 +1,15 @@
1
1
  # encoding: utf-8
2
2
  require "spec_helper"
3
3
  describe DoubleEntry::Line do
4
+ it "has a table name prefixed with double_entry_" do
5
+ expect(DoubleEntry::Line.table_name).to eq "double_entry_lines"
6
+ end
4
7
 
5
- describe "persistent attributes" do
8
+ describe "persistance" do
6
9
  let(:persisted_line) {
7
10
  DoubleEntry::Line.new(
8
11
  :amount => Money.new(10_00),
9
- :balance => Money.empty,
12
+ :balance => Money.zero,
10
13
  :account => account,
11
14
  :partner_account => partner_account,
12
15
  :code => code,
@@ -15,53 +18,61 @@ describe DoubleEntry::Line do
15
18
  let(:account) { DoubleEntry.account(:test, :scope => "17") }
16
19
  let(:partner_account) { DoubleEntry.account(:test, :scope => "72") }
17
20
  let(:code) { :test_code }
18
- before { persisted_line.save! }
19
21
  subject { DoubleEntry::Line.last }
20
22
 
21
- context "given code = :the_code" do
22
- let(:code) { :the_code }
23
- its(:code) { should eq :the_code }
24
- end
23
+ describe "attributes" do
24
+ before { persisted_line.save! }
25
25
 
26
- context "given code = nil" do
27
- let(:code) { nil }
28
- its(:code) { should eq nil }
29
- end
26
+ context "given code = :the_code" do
27
+ let(:code) { :the_code }
28
+ its(:code) { should eq :the_code }
29
+ end
30
30
 
31
- context "given account = :test, 54 " do
32
- let(:account) { DoubleEntry.account(:test, :scope => "54") }
33
- its("account.account.identifier") { should eq :test }
34
- its("account.scope") { should eq "54" }
35
- end
31
+ context "given code = nil" do
32
+ let(:code) { nil }
33
+ its(:code) { should eq nil }
34
+ end
35
+
36
+ context "given account = :test, 54 " do
37
+ let(:account) { DoubleEntry.account(:test, :scope => "54") }
38
+ its("account.account.identifier") { should eq :test }
39
+ its("account.scope") { should eq "54" }
40
+ end
36
41
 
37
- context "given partner_account = :test, 91 " do
38
- let(:partner_account) { DoubleEntry.account(:test, :scope => "91") }
39
- its("partner_account.account.identifier") { should eq :test }
40
- its("partner_account.scope") { should eq "91" }
42
+ context "given partner_account = :test, 91 " do
43
+ let(:partner_account) { DoubleEntry.account(:test, :scope => "91") }
44
+ its("partner_account.account.identifier") { should eq :test }
45
+ its("partner_account.scope") { should eq "91" }
46
+ end
47
+
48
+ context "currency" do
49
+ let(:account) { DoubleEntry.account(:btc_test, :scope => "17") }
50
+ let(:partner_account) { DoubleEntry.account(:btc_test, :scope => "72") }
51
+ its(:currency) { should eq "BTC" }
52
+ end
41
53
  end
42
- end
43
54
 
44
- describe '#save' do
45
- context 'when balance is sent negative' do
46
- let(:account) {
47
- DoubleEntry.account(:savings, :scope => '17', :positive_only => true)
48
- }
55
+ describe '#save' do
56
+ context 'when balance is sent negative' do
57
+ let(:account) {
58
+ DoubleEntry.account(:savings, :scope => '17', :positive_only => true)
59
+ }
49
60
 
50
- let(:line) {
51
- DoubleEntry::Line.new(
52
- :balance => Money.new(-1),
53
- :account => account,
54
- )
55
- }
61
+ let(:line) {
62
+ DoubleEntry::Line.new(
63
+ :balance => Money.new(-1),
64
+ :account => account,
65
+ )
66
+ }
56
67
 
57
- it 'raises AccountWouldBeSentNegative exception' do
58
- expect { line.save }.to raise_error DoubleEntry::AccountWouldBeSentNegative
68
+ it 'raises AccountWouldBeSentNegative exception' do
69
+ expect { line.save }.to raise_error DoubleEntry::AccountWouldBeSentNegative
70
+ end
59
71
  end
60
72
  end
61
- end
62
73
 
63
- it "has a table name prefixed with double_entry_" do
64
- expect(DoubleEntry::Line.table_name).to eq "double_entry_lines"
74
+ it "has a table name prefixed with double_entry_" do
75
+ expect(DoubleEntry::Line.table_name).to eq "double_entry_lines"
76
+ end
65
77
  end
66
-
67
78
  end
@@ -51,8 +51,8 @@ describe DoubleEntry::Locking do
51
51
  end
52
52
 
53
53
  it "takes the balance for new account balance records from the lines table" do
54
- DoubleEntry::Line.create!(:account => @account_a, :amount => Money.new(3_00), :balance => Money.new( 3_00), :code => :test)
55
- DoubleEntry::Line.create!(:account => @account_a, :amount => Money.new(7_00), :balance => Money.new(10_00), :code => :test)
54
+ DoubleEntry::Line.create!(:account => @account_a, :partner_account => @account_b, :amount => Money.new(3_00), :balance => Money.new( 3_00), :code => :test)
55
+ DoubleEntry::Line.create!(:account => @account_a, :partner_account => @account_b, :amount => Money.new(7_00), :balance => Money.new(10_00), :code => :test)
56
56
 
57
57
  expect do
58
58
  DoubleEntry::Locking.lock_accounts(@account_a) { }
@@ -8,12 +8,13 @@ module DoubleEntry
8
8
  let(:finish) { nil }
9
9
  let(:range_type) { 'year' }
10
10
  let(:function) { :sum }
11
-
11
+ let(:account) { :savings }
12
+ let(:transfer_code) { :bonus }
12
13
  subject(:aggregate_array) {
13
14
  Reporting.aggregate_array(
14
15
  function,
15
- :savings,
16
- :bonus,
16
+ account,
17
+ transfer_code,
17
18
  :range_type => range_type,
18
19
  :start => start,
19
20
  :finish => finish,
@@ -69,6 +70,20 @@ module DoubleEntry
69
70
  end
70
71
  end
71
72
 
73
+ context 'when account is in BTC currency' do
74
+ let(:account) { :btc_savings }
75
+ let(:range_type) { 'year' }
76
+ let(:start) { "#{Time.now.year}-01-01" }
77
+ let(:transfer_code) { :btc_test_transfer }
78
+
79
+ before do
80
+ perform_btc_deposit(user, 100_000_000)
81
+ perform_btc_deposit(user, 100_000_000)
82
+ end
83
+
84
+ it { should eq [ Money.new(200_000_000, :btc) ] }
85
+ end
86
+
72
87
  context 'when called with range type of "invalid_and_should_not_work"' do
73
88
  let(:range_type) { 'invalid_and_should_not_work' }
74
89
  it 'raises an argument error' do
@@ -203,5 +203,18 @@ module DoubleEntry
203
203
  end
204
204
  end
205
205
  end
206
+ describe Aggregate, "currencies" do
207
+ let(:user) { User.make! }
208
+ before do
209
+ perform_btc_deposit(user, 100_000_000)
210
+ perform_btc_deposit(user, 200_000_000)
211
+ end
212
+
213
+ it 'should calculate the sum in the correct currency' do
214
+ expect(
215
+ Reporting.aggregate(:sum, :btc_savings, :btc_test_transfer, :range => TimeRange.make(:year => Time.now.year))
216
+ ).to eq Money.new(300_000_000, :btc)
217
+ end
218
+ end
206
219
  end
207
220
  end
@@ -80,6 +80,22 @@ module DoubleEntry::Validation
80
80
  end
81
81
  end
82
82
 
83
+
84
+ context 'Given a user with a non default currency balance' do
85
+ before { User.make!(:bitcoin_balance => Money.new(100_00, 'BTC')) }
86
+ its(:errors_found) { should eq false }
87
+ context 'And there is a consistency error in lines' do
88
+ before { DoubleEntry::Line.order(:id).limit(1).update_all('balance = balance + 1') }
89
+
90
+ its(:errors_found) { should eq true }
91
+ it 'should correct the running balance' do
92
+ expect {
93
+ LineCheck.perform!
94
+ }.to change { DoubleEntry::Line.order(:id).first.balance }.by Money.new(-1, 'BTC')
95
+ end
96
+ end
97
+ end
98
+
83
99
  it "has a table name prefixed with double_entry_" do
84
100
  expect(LineCheck.table_name).to eq "double_entry_line_checks"
85
101
  end
@@ -97,17 +97,20 @@ describe DoubleEntry do
97
97
  accounts.define(:identifier => :savings)
98
98
  accounts.define(:identifier => :cash)
99
99
  accounts.define(:identifier => :trash)
100
+ accounts.define(:identifier => :bitbucket, :currency => :btc)
100
101
  end
101
102
 
102
103
  config.define_transfers do |transfers|
103
104
  transfers.define(:from => :savings, :to => :cash, :code => :xfer)
105
+ transfers.define(:from => :trash, :to => :bitbucket, :code => :mismatch_xfer)
104
106
  end
105
107
  end
106
108
  end
107
109
 
108
- let(:savings) { DoubleEntry.account(:savings) }
109
- let(:cash) { DoubleEntry.account(:cash) }
110
- let(:trash) { DoubleEntry.account(:trash) }
110
+ let(:savings) { DoubleEntry.account(:savings) }
111
+ let(:cash) { DoubleEntry.account(:cash) }
112
+ let(:trash) { DoubleEntry.account(:trash) }
113
+ let(:bitbucket) { DoubleEntry.account(:bitbucket) }
111
114
 
112
115
  it 'can transfer from an account to an account, if the transfer is allowed' do
113
116
  DoubleEntry.transfer(
@@ -149,6 +152,17 @@ describe DoubleEntry do
149
152
  )
150
153
  }.to raise_error DoubleEntry::TransferNotAllowed
151
154
  end
155
+
156
+ it 'raises an exception when the transfer is not allowed (mismatched currencies)' do
157
+ expect {
158
+ DoubleEntry.transfer(
159
+ Money.new(100_00),
160
+ :from => trash,
161
+ :to => bitbucket,
162
+ :code => :mismatch_xfer
163
+ )
164
+ }.to raise_error DoubleEntry::MismatchedCurrencies
165
+ end
152
166
  end
153
167
 
154
168
  describe 'lines' do
@@ -219,10 +233,12 @@ describe DoubleEntry do
219
233
 
220
234
  describe 'balances' do
221
235
 
222
- let(:work) { DoubleEntry.account(:work) }
223
- let(:savings) { DoubleEntry.account(:savings) }
224
- let(:cash) { DoubleEntry.account(:cash) }
225
- let(:store) { DoubleEntry.account(:store) }
236
+ let(:work) { DoubleEntry.account(:work) }
237
+ let(:savings) { DoubleEntry.account(:savings) }
238
+ let(:cash) { DoubleEntry.account(:cash) }
239
+ let(:store) { DoubleEntry.account(:store) }
240
+ let(:btc_store) { DoubleEntry.account(:btc_store) }
241
+ let(:btc_wallet) { DoubleEntry.account(:btc_wallet) }
226
242
 
227
243
  before do
228
244
  DoubleEntry.configure do |config|
@@ -231,6 +247,8 @@ describe DoubleEntry do
231
247
  accounts.define(:identifier => :cash)
232
248
  accounts.define(:identifier => :savings)
233
249
  accounts.define(:identifier => :store)
250
+ accounts.define(:identifier => :btc_store, :currency => 'BTC')
251
+ accounts.define(:identifier => :btc_wallet, :currency => 'BTC')
234
252
  end
235
253
 
236
254
  config.define_transfers do |transfers|
@@ -240,6 +258,7 @@ describe DoubleEntry do
240
258
  transfers.define(:code => :purchase, :from => :cash, :to => :store)
241
259
  transfers.define(:code => :layby, :from => :cash, :to => :store)
242
260
  transfers.define(:code => :deposit, :from => :cash, :to => :store)
261
+ transfers.define(:code => :btc_ex, :from => :btc_store, :to => :btc_wallet)
243
262
  end
244
263
  end
245
264
 
@@ -267,7 +286,8 @@ describe DoubleEntry do
267
286
  end
268
287
 
269
288
  Timecop.freeze 1.week.from_now do
270
- # go to the star wars convention AND ROCK OUT IN YOUR ACE DARTH VADER COSTUME!!!
289
+ # it's the future, man
290
+ DoubleEntry.transfer(Money.new(200_00, 'BTC'), :from => btc_store, :code => :btc_ex, :to => btc_wallet)
271
291
  end
272
292
  end
273
293
 
@@ -276,14 +296,19 @@ describe DoubleEntry do
276
296
  expect(cash.balance).to eq Money.new(100_00)
277
297
  expect(savings.balance).to eq Money.new(300_00)
278
298
  expect(store.balance).to eq Money.new(600_00)
299
+ expect(btc_wallet.balance).to eq Money.new(200_00, 'BTC')
279
300
  end
280
301
 
281
302
  it 'should have correct account balance records' do
282
- [work, cash, savings, store].each do |account|
303
+ [work, cash, savings, store, btc_wallet].each do |account|
283
304
  expect(DoubleEntry::AccountBalance.find_by_account(account).balance).to eq account.balance
284
305
  end
285
306
  end
286
307
 
308
+ it 'should have correct account balance currencies' do
309
+ expect(DoubleEntry::AccountBalance.find_by_account(btc_wallet).balance.currency).to eq 'BTC'
310
+ end
311
+
287
312
  it 'affects origin/destination balance after transfer' do
288
313
  savings_balance = savings.balance
289
314
  cash_balance = cash.balance
@@ -303,6 +328,10 @@ describe DoubleEntry do
303
328
  expect(cash.balance(:from => 3.weeks.ago, :to => 2.weeks.ago)).to eq Money.new(500_00)
304
329
  end
305
330
 
331
+ it 'can be queried between two points in time, even in the future' do
332
+ expect(btc_wallet.balance(:from => Time.now, :to => 2.weeks.from_now)).to eq Money.new(200_00, 'BTC')
333
+ end
334
+
306
335
  it 'can report on balances, scoped by code' do
307
336
  expect(cash.balance(:code => :salary)).to eq Money.new(1_000_00)
308
337
  end
@@ -341,6 +370,8 @@ describe DoubleEntry do
341
370
  end
342
371
 
343
372
  let(:bank) { DoubleEntry.account(:bank) }
373
+ let(:cash) { DoubleEntry.account(:cash) }
374
+ let(:savings) { DoubleEntry.account(:savings) }
344
375
 
345
376
  let(:john) { User.make! }
346
377
  let(:johns_cash) { DoubleEntry.account(:cash, :scope => john) }
@@ -386,5 +417,4 @@ describe DoubleEntry do
386
417
  expect(DoubleEntry.balance(:savings)).to eq ryans_savings.balance + johns_savings.balance
387
418
  end
388
419
  end
389
-
390
420
  end
data/spec/spec_helper.rb CHANGED
@@ -5,11 +5,19 @@ require 'active_support'
5
5
 
6
6
  db_engine = ENV['DB'] || 'mysql'
7
7
 
8
- ActiveRecord::Base.establish_connection YAML.load_file(File.expand_path("../support/database.yml", __FILE__))[db_engine]
9
-
8
+ FileUtils.mkdir_p 'tmp'
10
9
  FileUtils.mkdir_p 'log'
11
10
  FileUtils.rm 'log/test.log', :force => true
12
11
 
12
+ database_config_file = File.expand_path("../support/database.yml", __FILE__)
13
+ if File.exists?(database_config_file)
14
+ ActiveRecord::Base.establish_connection YAML.load_file(database_config_file)[db_engine]
15
+ else
16
+ puts "Please configure your spec/support/database.yml file."
17
+ puts "See spec/support/database.example.yml"
18
+ exit 1
19
+ end
20
+
13
21
  # Buffered Logger was deprecated in ActiveSupport 4.0.0 and was removed in 4.1.0
14
22
  # Logger was added in ActiveSupport 4.0.0
15
23
  if defined? ActiveSupport::Logger
@@ -33,16 +41,14 @@ RSpec.configure do |config|
33
41
  config.include DoubleEntrySpecHelper
34
42
 
35
43
  config.before(:suite) do
36
- DatabaseCleaner.strategy = :deletion
37
- DatabaseCleaner.clean_with(:deletion)
44
+ DatabaseCleaner.strategy = :truncation
38
45
  end
39
46
 
40
- config.before(:each) do
41
- DatabaseCleaner.start
47
+ config.before do
48
+ DatabaseCleaner.clean
42
49
  end
43
50
 
44
- config.after(:each) do
51
+ config.after do
45
52
  Timecop.return
46
- DatabaseCleaner.clean
47
53
  end
48
54
  end
@@ -5,15 +5,19 @@ DoubleEntry.configure do |config|
5
5
  # A set of accounts to test with
6
6
  config.define_accounts do |accounts|
7
7
  user_scope = accounts.active_record_scope_identifier(User)
8
- accounts.define(:identifier => :savings, :scope_identifier => user_scope, :positive_only => true)
9
- accounts.define(:identifier => :checking, :scope_identifier => user_scope, :positive_only => true)
10
- accounts.define(:identifier => :test, :scope_identifier => user_scope)
8
+ accounts.define(:identifier => :savings, :scope_identifier => user_scope, :positive_only => true)
9
+ accounts.define(:identifier => :checking, :scope_identifier => user_scope, :positive_only => true)
10
+ accounts.define(:identifier => :test, :scope_identifier => user_scope)
11
+ accounts.define(:identifier => :btc_test, :scope_identifier => user_scope, :currency => "BTC")
12
+ accounts.define(:identifier => :btc_savings, :scope_identifier => user_scope, :currency => "BTC")
11
13
  end
12
14
 
13
15
  # A set of allowed transfers between accounts
14
16
  config.define_transfers do |transfers|
15
- transfers.define(:from => :test, :to => :savings, :code => :bonus)
16
- transfers.define(:from => :test, :to => :checking, :code => :pay)
17
+ transfers.define(:from => :test, :to => :savings, :code => :bonus)
18
+ transfers.define(:from => :test, :to => :checking, :code => :pay)
19
+ transfers.define(:from => :savings, :to => :test, :code => :test_withdrawal)
20
+ transfers.define(:from => :btc_test, :to => :btc_savings, :code => :btc_test_transfer)
17
21
  end
18
22
 
19
23
  end
@@ -2,6 +2,7 @@ class UserBlueprint < Machinist::ActiveRecord::Blueprint
2
2
  def make!(attributes = {})
3
3
  savings_balance = attributes.delete(:savings_balance)
4
4
  checking_balance = attributes.delete(:checking_balance)
5
+ bitcoin_balance = attributes.delete(:bitcoin_balance)
5
6
  user = super(attributes)
6
7
  if savings_balance
7
8
  DoubleEntry.transfer(
@@ -19,6 +20,14 @@ class UserBlueprint < Machinist::ActiveRecord::Blueprint
19
20
  :code => :pay,
20
21
  )
21
22
  end
23
+ if bitcoin_balance
24
+ DoubleEntry.transfer(
25
+ bitcoin_balance,
26
+ :from => DoubleEntry.account(:btc_test, :scope => user),
27
+ :to => DoubleEntry.account(:btc_savings, :scope => user),
28
+ :code => :btc_test_transfer,
29
+ )
30
+ end
22
31
  user
23
32
  end
24
33
  end
@@ -17,5 +17,5 @@ mysql:
17
17
  sqlite:
18
18
  adapter: sqlite3
19
19
  encoding: utf8
20
- database: db/double_entry_test.sqlite3
20
+ database: tmp/double_entry_test.sqlite3
21
21
  pool: 100
@@ -20,5 +20,5 @@ postgres:
20
20
  sqlite:
21
21
  adapter: sqlite3
22
22
  encoding: utf8
23
- database: db/double_entry_test.sqlite3
23
+ database: tmp/double_entry_test.sqlite3
24
24
  pool: 100
@@ -16,4 +16,12 @@ module DoubleEntrySpecHelper
16
16
  )
17
17
  end
18
18
 
19
+ def perform_btc_deposit(user, amount)
20
+ DoubleEntry.transfer(Money.new(amount, :btc),
21
+ :from => DoubleEntry.account(:btc_test, :scope => user),
22
+ :to => DoubleEntry.account(:btc_savings, :scope => user),
23
+ :code => :btc_test_transfer,
24
+ )
25
+ end
26
+
19
27
  end
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gemspec :path => '../'
3
+ gemspec :path => '../../../'
4
4
 
5
5
  gem 'i18n', '0.6.11'
6
- gem 'rails', '~>3.2.0'
6
+ gem 'rails', '~> 3.2.0'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec :path => '../../../'
4
+
5
+ gem 'rails', '~> 4.0.0'
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec :path => '../../../'
4
+
5
+ gem 'rails', '~> 4.1.0'
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.6.1
4
+ version: 0.7.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: 2014-10-10 00:00:00.000000000 Z
18
+ date: 2014-11-12 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: money
@@ -23,70 +23,56 @@ dependencies:
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 5.1.0
26
+ version: 6.0.0
27
27
  type: :runtime
28
28
  prerelease: false
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 5.1.0
34
- - !ruby/object:Gem::Dependency
35
- name: encapsulate_as_money
36
- requirement: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- type: :runtime
42
- prerelease: false
43
- version_requirements: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
33
+ version: 6.0.0
48
34
  - !ruby/object:Gem::Dependency
49
35
  name: activerecord
50
36
  requirement: !ruby/object:Gem::Requirement
51
37
  requirements:
52
38
  - - ">="
53
39
  - !ruby/object:Gem::Version
54
- version: 3.2.9
40
+ version: 3.2.0
55
41
  type: :runtime
56
42
  prerelease: false
57
43
  version_requirements: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - ">="
60
46
  - !ruby/object:Gem::Version
61
- version: 3.2.9
47
+ version: 3.2.0
62
48
  - !ruby/object:Gem::Dependency
63
49
  name: activesupport
64
50
  requirement: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - ">="
67
53
  - !ruby/object:Gem::Version
68
- version: 3.0.0
54
+ version: 3.2.0
69
55
  type: :runtime
70
56
  prerelease: false
71
57
  version_requirements: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - ">="
74
60
  - !ruby/object:Gem::Version
75
- version: 3.0.0
61
+ version: 3.2.0
76
62
  - !ruby/object:Gem::Dependency
77
63
  name: railties
78
64
  requirement: !ruby/object:Gem::Requirement
79
65
  requirements:
80
66
  - - ">="
81
67
  - !ruby/object:Gem::Version
82
- version: 3.0.0
68
+ version: 3.2.0
83
69
  type: :runtime
84
70
  prerelease: false
85
71
  version_requirements: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - ">="
88
74
  - !ruby/object:Gem::Version
89
- version: 3.0.0
75
+ version: 3.2.0
90
76
  - !ruby/object:Gem::Dependency
91
77
  name: rake
92
78
  requirement: !ruby/object:Gem::Requirement
@@ -249,11 +235,7 @@ files:
249
235
  - LICENSE.md
250
236
  - README.md
251
237
  - Rakefile
252
- - db/.gitkeep
253
238
  - double_entry.gemspec
254
- - gemfiles/Gemfile.rails-3.2.0
255
- - gemfiles/Gemfile.rails-4.0.0
256
- - gemfiles/Gemfile.rails-4.1.0
257
239
  - lib/active_record/locking_extensions.rb
258
240
  - lib/double_entry.rb
259
241
  - lib/double_entry/account.rb
@@ -308,6 +290,9 @@ files:
308
290
  - spec/support/database.example.yml
309
291
  - spec/support/database.travis.yml
310
292
  - spec/support/double_entry_spec_helper.rb
293
+ - spec/support/gemfiles/Gemfile.rails-3.2.x
294
+ - spec/support/gemfiles/Gemfile.rails-4.0.x
295
+ - spec/support/gemfiles/Gemfile.rails-4.1.x
311
296
  - spec/support/reporting_configuration.rb
312
297
  - spec/support/schema.rb
313
298
  homepage: https://github.com/envato/double_entry
@@ -359,5 +344,8 @@ test_files:
359
344
  - spec/support/database.example.yml
360
345
  - spec/support/database.travis.yml
361
346
  - spec/support/double_entry_spec_helper.rb
347
+ - spec/support/gemfiles/Gemfile.rails-3.2.x
348
+ - spec/support/gemfiles/Gemfile.rails-4.0.x
349
+ - spec/support/gemfiles/Gemfile.rails-4.1.x
362
350
  - spec/support/reporting_configuration.rb
363
351
  - spec/support/schema.rb
data/db/.gitkeep DELETED
File without changes
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '../'
4
-
5
- gem 'rails', '~>4.0.0'
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '../'
4
-
5
- gem 'rails', '~>4.1.0'