double_entry 2.0.0.beta3 → 2.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/README.md +10 -3
- data/double_entry.gemspec +1 -1
- data/lib/double_entry.rb +11 -2
- data/lib/double_entry/configurable.rb +1 -0
- data/lib/double_entry/configuration.rb +6 -0
- data/lib/double_entry/line.rb +1 -1
- data/lib/double_entry/locking.rb +3 -3
- data/lib/double_entry/transfer.rb +4 -3
- data/lib/double_entry/version.rb +1 -1
- data/lib/generators/double_entry/install/install_generator.rb +15 -0
- data/lib/generators/double_entry/install/templates/initializer.rb +20 -0
- data/lib/generators/double_entry/install/templates/migration.rb +14 -5
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c695b54b7cec66c99e9e6e62e0452883412b2a73596d5ea6deae695d48403f7
|
4
|
+
data.tar.gz: e12facb9d3741e7d461788534826c93f0827fd08f90898d831ea0777879d9204
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f99f15db2934b0f5ca49f640a1373aefef4ca37fc62303afa440ff71c671783f586345149e681566cc9c27543c8f6c4979921ea457ccd5e46c68f3d20363d010
|
7
|
+
data.tar.gz: 215d09cbc9a0aafdd1fa6ebb518a0a86aea0ea8c757afe528126dbb95e0772ade2edb8948ddfa46445258102a12f09b41f81192f96495e26dbade111cab3ef01
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
[Unreleased]: https://github.com/envato/double_entry/compare/v2.0.0.beta4...HEAD
|
11
|
+
|
12
|
+
## [2.0.0.beta4] - 2020-01-25
|
13
|
+
|
14
|
+
### Added
|
15
|
+
|
16
|
+
- Test against Rails 6.0, ([#176]).
|
17
|
+
|
18
|
+
- Support for Ruby 2.7 ([#180]).
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
|
22
|
+
- Metadata stored by default in a json(b) column for new installs ([#178]).
|
23
|
+
|
24
|
+
- Remove `force: true` from migration ([#181]).
|
25
|
+
|
26
|
+
- Prevent using Ruby 2.2 via restrictions in Gemfile and Gemspec ([#175]).
|
27
|
+
|
28
|
+
[2.0.0.beta4]: https://github.com/envato/double_entry/compare/v2.0.0.beta3...v2.0.0.beta4
|
29
|
+
[#175]: https://github.com/envato/double_entry/pull/175
|
30
|
+
[#176]: https://github.com/envato/double_entry/pull/176
|
31
|
+
[#178]: https://github.com/envato/double_entry/pull/178
|
32
|
+
[#180]: https://github.com/envato/double_entry/pull/180
|
33
|
+
[#181]: https://github.com/envato/double_entry/pull/181
|
34
|
+
|
10
35
|
## [2.0.0.beta3] - 2019-11-14
|
11
36
|
|
12
37
|
### Fixed
|
@@ -437,7 +462,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
437
462
|
|
438
463
|
- Library released as Open Source!
|
439
464
|
|
440
|
-
[Unreleased]: https://github.com/envato/double_entry/compare/v2.0.0.beta3...HEAD
|
441
465
|
[2.0.0.beta3]: https://github.com/envato/double_entry/compare/v2.0.0.beta2...v2.0.0.beta3
|
442
466
|
[2.0.0.beta2]: https://github.com/envato/double_entry/compare/v2.0.0.beta1...v2.0.0.beta2
|
443
467
|
[2.0.0.beta1]: https://github.com/envato/double_entry/compare/v1.0.1...v2.0.0.beta1
|
data/README.md
CHANGED
@@ -26,12 +26,14 @@ Ruby
|
|
26
26
|
* 2.4.x
|
27
27
|
* 2.5.x
|
28
28
|
* 2.6.x
|
29
|
+
* 2.7.x
|
29
30
|
|
30
31
|
Rails
|
31
32
|
* 4.2.x
|
32
33
|
* 5.0.x
|
33
34
|
* 5.1.x
|
34
35
|
* 5.2.x
|
36
|
+
* 6.0.x
|
35
37
|
|
36
38
|
Databases
|
37
39
|
* MySQL
|
@@ -54,6 +56,8 @@ bundle
|
|
54
56
|
|
55
57
|
Generate Rails schema migrations for the required tables:
|
56
58
|
|
59
|
+
> The default behavior is to store metadata in a json(b) column rather than a separate `double_entry_line_metadata` table. If you would like the old (1.x) behavior, you can add `--no-json-metadata`.
|
60
|
+
|
57
61
|
```sh
|
58
62
|
rails generate double_entry:install
|
59
63
|
```
|
@@ -174,8 +178,7 @@ See **DoubleEntry::Line** for more info.
|
|
174
178
|
AccountBalance records cache the current balance for each Account, and are used
|
175
179
|
to perform database level locking.
|
176
180
|
|
177
|
-
Transfer metadata is stored
|
178
|
-
See **DoubleEntry::LineMetadata** for more info.
|
181
|
+
Transfer metadata is stored in a json(b) column on both the source and destination lines of the transfer.
|
179
182
|
|
180
183
|
## Configuration
|
181
184
|
|
@@ -183,7 +186,7 @@ A configuration file should be used to define a set of accounts, optional scopes
|
|
183
186
|
the accounts, and permitted transfers between those accounts.
|
184
187
|
|
185
188
|
The configuration file should be kept in your application's load path. For example,
|
186
|
-
*config/initializers/double_entry.rb
|
189
|
+
*config/initializers/double_entry.rb*. By default, this file will be created when you run the installer, but you will need to fill out your accounts.
|
187
190
|
|
188
191
|
For example, the following specifies two accounts, savings and checking.
|
189
192
|
Each account is scoped by User (where User is an object with an ID), meaning
|
@@ -195,6 +198,9 @@ This configuration also specifies that money can be transferred between the two
|
|
195
198
|
require 'double_entry'
|
196
199
|
|
197
200
|
DoubleEntry.configure do |config|
|
201
|
+
# Use json(b) column in double_entry_lines table to store metadata instead of separate metadata table
|
202
|
+
config.json_metadata = true
|
203
|
+
|
198
204
|
config.define_accounts do |accounts|
|
199
205
|
user_scope = ->(user) do
|
200
206
|
raise 'not a User' unless user.class.name == 'User'
|
@@ -328,6 +334,7 @@ Many thanks to those who have contributed to both this gem, and the library upon
|
|
328
334
|
* Rizal Muthi - @rizalmuthi
|
329
335
|
* Ryan Allen - @ryan-allen
|
330
336
|
* Samuel Cochran - @sj26
|
337
|
+
* Stefan Wrobel - @swrobel
|
331
338
|
* Stephanie Staub - @stephnacios
|
332
339
|
* Trung Lê - @joneslee85
|
333
340
|
* Vahid Ta'eed - @vahid
|
data/double_entry.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |gem|
|
|
24
24
|
f.match(%r{^(?:double_entry.gemspec|README|LICENSE|CHANGELOG|lib/)})
|
25
25
|
end
|
26
26
|
gem.require_paths = ['lib']
|
27
|
-
gem.required_ruby_version = '>= 2.
|
27
|
+
gem.required_ruby_version = '>= 2.3.0'
|
28
28
|
|
29
29
|
gem.add_dependency 'activerecord', '>= 3.2.0'
|
30
30
|
gem.add_dependency 'activesupport', '>= 3.2.0'
|
data/lib/double_entry.rb
CHANGED
@@ -4,6 +4,7 @@ require 'active_record/locking_extensions'
|
|
4
4
|
require 'active_record/locking_extensions/log_subscriber'
|
5
5
|
require 'active_support/all'
|
6
6
|
require 'money'
|
7
|
+
require 'rails/railtie'
|
7
8
|
|
8
9
|
require 'double_entry/version'
|
9
10
|
require 'double_entry/errors'
|
@@ -14,8 +15,6 @@ require 'double_entry/account_balance'
|
|
14
15
|
require 'double_entry/balance_calculator'
|
15
16
|
require 'double_entry/locking'
|
16
17
|
require 'double_entry/transfer'
|
17
|
-
require 'double_entry/line'
|
18
|
-
require 'double_entry/line_metadata'
|
19
18
|
require 'double_entry/validation'
|
20
19
|
|
21
20
|
# Keep track of all the monies!
|
@@ -23,6 +22,16 @@ require 'double_entry/validation'
|
|
23
22
|
# This module provides the public interfaces for everything to do with
|
24
23
|
# transferring money around the system.
|
25
24
|
module DoubleEntry
|
25
|
+
class Railtie < ::Rails::Railtie
|
26
|
+
# So we can access user config from initializer in their app
|
27
|
+
config.after_initialize do
|
28
|
+
unless DoubleEntry.config.json_metadata
|
29
|
+
require 'double_entry/line_metadata'
|
30
|
+
end
|
31
|
+
require 'double_entry/line'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
26
35
|
class << self
|
27
36
|
# Get the particular account instance with the provided identifier and
|
28
37
|
# scope.
|
data/lib/double_entry/line.rb
CHANGED
@@ -56,7 +56,7 @@ module DoubleEntry
|
|
56
56
|
#
|
57
57
|
class Line < ActiveRecord::Base
|
58
58
|
belongs_to :detail, :polymorphic => true
|
59
|
-
has_many :metadata, :class_name => 'DoubleEntry::LineMetadata'
|
59
|
+
has_many :metadata, :class_name => 'DoubleEntry::LineMetadata' unless -> { DoubleEntry.config.json_metadata }
|
60
60
|
scope :with_id_greater_than, ->(id) { where('id > ?', id) }
|
61
61
|
|
62
62
|
def amount
|
data/lib/double_entry/locking.rb
CHANGED
@@ -32,14 +32,14 @@ module DoubleEntry
|
|
32
32
|
#
|
33
33
|
# The transaction must be the outermost transaction to ensure data integrity. A
|
34
34
|
# LockMustBeOutermostTransaction will be raised if it isn't.
|
35
|
-
def self.lock_accounts(*accounts)
|
35
|
+
def self.lock_accounts(*accounts, &block)
|
36
36
|
lock = Lock.new(accounts)
|
37
37
|
|
38
38
|
if lock.in_a_locked_transaction?
|
39
39
|
lock.ensure_locked!
|
40
|
-
|
40
|
+
block.call
|
41
41
|
else
|
42
|
-
lock.perform_lock(&
|
42
|
+
lock.perform_lock(&block)
|
43
43
|
end
|
44
44
|
|
45
45
|
rescue ActiveRecord::StatementInvalid => exception
|
@@ -88,12 +88,12 @@ module DoubleEntry
|
|
88
88
|
fail MismatchedCurrencies, "Mismatched currency (#{to_account.currency} <> #{from_account.currency})"
|
89
89
|
end
|
90
90
|
Locking.lock_accounts(from_account, to_account) do
|
91
|
-
credit, debit = create_lines(amount, code, detail, from_account, to_account)
|
92
|
-
create_line_metadata(credit, debit, metadata) if metadata
|
91
|
+
credit, debit = create_lines(amount, code, detail, from_account, to_account, metadata)
|
92
|
+
create_line_metadata(credit, debit, metadata) if metadata && !DoubleEntry.config.json_metadata
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
def create_lines(amount, code, detail, from_account, to_account)
|
96
|
+
def create_lines(amount, code, detail, from_account, to_account, metadata)
|
97
97
|
credit, debit = Line.new, Line.new
|
98
98
|
|
99
99
|
credit_balance = Locking.balance_for_locked_account(from_account)
|
@@ -107,6 +107,7 @@ module DoubleEntry
|
|
107
107
|
credit.code, debit.code = code, code
|
108
108
|
credit.detail, debit.detail = detail, detail
|
109
109
|
credit.balance, debit.balance = credit_balance.balance, debit_balance.balance
|
110
|
+
credit.metadata, debit.metadata = metadata, metadata if DoubleEntry.config.json_metadata
|
110
111
|
|
111
112
|
credit.partner_account, debit.partner_account = to_account, from_account
|
112
113
|
|
data/lib/double_entry/version.rb
CHANGED
@@ -7,6 +7,8 @@ module DoubleEntry
|
|
7
7
|
class InstallGenerator < Rails::Generators::Base
|
8
8
|
include Rails::Generators::Migration
|
9
9
|
|
10
|
+
class_option :json_metadata, type: :boolean, default: true
|
11
|
+
|
10
12
|
source_root File.expand_path('../templates', __FILE__)
|
11
13
|
|
12
14
|
def self.next_migration_number(path)
|
@@ -17,6 +19,19 @@ module DoubleEntry
|
|
17
19
|
migration_template 'migration.rb', 'db/migrate/create_double_entry_tables.rb', migration_version: migration_version
|
18
20
|
end
|
19
21
|
|
22
|
+
def create_initializer
|
23
|
+
template 'initializer.rb', 'config/initializers/double_entry.rb'
|
24
|
+
end
|
25
|
+
|
26
|
+
def json_metadata
|
27
|
+
# MySQL JSON support added to AR 5.0
|
28
|
+
if ActiveRecord.version.version < '5'
|
29
|
+
false
|
30
|
+
else
|
31
|
+
options[:json_metadata]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
20
35
|
def migration_version
|
21
36
|
if ActiveRecord.version.version > '5'
|
22
37
|
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'double_entry'
|
2
|
+
|
3
|
+
DoubleEntry.configure do |config|
|
4
|
+
# Use json(b) column in double_entry_lines table to store metadata instead of separate metadata table
|
5
|
+
config.json_metadata = <%= json_metadata %>
|
6
|
+
|
7
|
+
# config.define_accounts do |accounts|
|
8
|
+
# user_scope = ->(user) do
|
9
|
+
# raise 'not a User' unless user.class.name == 'User'
|
10
|
+
# user.id
|
11
|
+
# end
|
12
|
+
# accounts.define(:identifier => :savings, :scope_identifier => user_scope, :positive_only => true)
|
13
|
+
# accounts.define(:identifier => :checking, :scope_identifier => user_scope)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# config.define_transfers do |transfers|
|
17
|
+
# transfers.define(:from => :checking, :to => :savings, :code => :deposit)
|
18
|
+
# transfers.define(:from => :savings, :to => :checking, :code => :withdraw)
|
19
|
+
# end
|
20
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class CreateDoubleEntryTables < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def self.up
|
3
|
-
create_table "double_entry_account_balances"
|
3
|
+
create_table "double_entry_account_balances" do |t|
|
4
4
|
t.string "account", :null => false
|
5
5
|
t.string "scope"
|
6
6
|
t.bigint "balance", :null => false
|
@@ -10,7 +10,7 @@ class CreateDoubleEntryTables < ActiveRecord::Migration<%= migration_version %>
|
|
10
10
|
add_index "double_entry_account_balances", ["account"], :name => "index_account_balances_on_account"
|
11
11
|
add_index "double_entry_account_balances", ["scope", "account"], :name => "index_account_balances_on_scope_and_account", :unique => true
|
12
12
|
|
13
|
-
create_table "double_entry_lines"
|
13
|
+
create_table "double_entry_lines" do |t|
|
14
14
|
t.string "account", :null => false
|
15
15
|
t.string "scope"
|
16
16
|
t.string "code", :null => false
|
@@ -20,6 +20,13 @@ class CreateDoubleEntryTables < ActiveRecord::Migration<%= migration_version %>
|
|
20
20
|
t.string "partner_account", :null => false
|
21
21
|
t.string "partner_scope"
|
22
22
|
t.references "detail", :index => false, :polymorphic => true
|
23
|
+
<%- if json_metadata -%>
|
24
|
+
if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
|
25
|
+
t.jsonb "metadata"
|
26
|
+
else
|
27
|
+
t.json "metadata"
|
28
|
+
end
|
29
|
+
<%- end -%>
|
23
30
|
t.timestamps :null => false
|
24
31
|
end
|
25
32
|
|
@@ -28,7 +35,7 @@ class CreateDoubleEntryTables < ActiveRecord::Migration<%= migration_version %>
|
|
28
35
|
add_index "double_entry_lines", ["scope", "account", "created_at"], :name => "lines_scope_account_created_at_idx"
|
29
36
|
add_index "double_entry_lines", ["scope", "account", "id"], :name => "lines_scope_account_id_idx"
|
30
37
|
|
31
|
-
create_table "double_entry_line_checks"
|
38
|
+
create_table "double_entry_line_checks" do |t|
|
32
39
|
t.references "last_line", :null => false, :index => false
|
33
40
|
t.boolean "errors_found", :null => false
|
34
41
|
t.text "log"
|
@@ -36,8 +43,9 @@ class CreateDoubleEntryTables < ActiveRecord::Migration<%= migration_version %>
|
|
36
43
|
end
|
37
44
|
|
38
45
|
add_index "double_entry_line_checks", ["created_at", "last_line_id"], :name => "line_checks_created_at_last_line_id_idx"
|
46
|
+
<%- unless json_metadata -%>
|
39
47
|
|
40
|
-
create_table "double_entry_line_metadata"
|
48
|
+
create_table "double_entry_line_metadata" do |t|
|
41
49
|
t.references "line", :null => false, :index => false
|
42
50
|
t.string "key", :null => false
|
43
51
|
t.string "value", :null => false
|
@@ -45,10 +53,11 @@ class CreateDoubleEntryTables < ActiveRecord::Migration<%= migration_version %>
|
|
45
53
|
end
|
46
54
|
|
47
55
|
add_index "double_entry_line_metadata", ["line_id", "key", "value"], :name => "lines_meta_line_id_key_value_idx"
|
56
|
+
<%- end -%>
|
48
57
|
end
|
49
58
|
|
50
59
|
def self.down
|
51
|
-
drop_table "double_entry_line_metadata"
|
60
|
+
drop_table "double_entry_line_metadata" if table_exists?("double_entry_line_metadata")
|
52
61
|
drop_table "double_entry_line_checks"
|
53
62
|
drop_table "double_entry_lines"
|
54
63
|
drop_table "double_entry_account_balances"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: double_entry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Envato
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -249,15 +249,16 @@ files:
|
|
249
249
|
- lib/double_entry/validation/line_check.rb
|
250
250
|
- lib/double_entry/version.rb
|
251
251
|
- lib/generators/double_entry/install/install_generator.rb
|
252
|
+
- lib/generators/double_entry/install/templates/initializer.rb
|
252
253
|
- lib/generators/double_entry/install/templates/migration.rb
|
253
254
|
homepage: https://github.com/envato/double_entry
|
254
255
|
licenses:
|
255
256
|
- MIT
|
256
257
|
metadata:
|
257
258
|
bug_tracker_uri: https://github.com/envato/double_entry/issues
|
258
|
-
changelog_uri: https://github.com/envato/double_entry/blob/v2.0.0.
|
259
|
-
documentation_uri: https://www.rubydoc.info/gems/double_entry/2.0.0.
|
260
|
-
source_code_uri: https://github.com/envato/double_entry/tree/v2.0.0.
|
259
|
+
changelog_uri: https://github.com/envato/double_entry/blob/v2.0.0.beta4/CHANGELOG.md
|
260
|
+
documentation_uri: https://www.rubydoc.info/gems/double_entry/2.0.0.beta4
|
261
|
+
source_code_uri: https://github.com/envato/double_entry/tree/v2.0.0.beta4
|
261
262
|
post_install_message:
|
262
263
|
rdoc_options: []
|
263
264
|
require_paths:
|
@@ -266,14 +267,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
266
267
|
requirements:
|
267
268
|
- - ">="
|
268
269
|
- !ruby/object:Gem::Version
|
269
|
-
version: 2.
|
270
|
+
version: 2.3.0
|
270
271
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
271
272
|
requirements:
|
272
273
|
- - ">"
|
273
274
|
- !ruby/object:Gem::Version
|
274
275
|
version: 1.3.1
|
275
276
|
requirements: []
|
276
|
-
rubygems_version: 3.
|
277
|
+
rubygems_version: 3.1.2
|
277
278
|
signing_key:
|
278
279
|
specification_version: 4
|
279
280
|
summary: Tools to build your double entry financial ledger
|