double_entry 2.0.0.beta3 → 2.0.0.beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|