double_entry 0.6.1 → 0.7.0

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