double_entry 1.0.1 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +432 -0
  3. data/README.md +36 -9
  4. data/double_entry.gemspec +20 -48
  5. data/lib/active_record/locking_extensions.rb +3 -3
  6. data/lib/active_record/locking_extensions/log_subscriber.rb +1 -1
  7. data/lib/double_entry/account.rb +38 -45
  8. data/lib/double_entry/account_balance.rb +18 -1
  9. data/lib/double_entry/errors.rb +13 -13
  10. data/lib/double_entry/line.rb +3 -2
  11. data/lib/double_entry/reporting.rb +26 -38
  12. data/lib/double_entry/reporting/aggregate.rb +43 -23
  13. data/lib/double_entry/reporting/aggregate_array.rb +16 -13
  14. data/lib/double_entry/reporting/line_aggregate.rb +3 -2
  15. data/lib/double_entry/reporting/line_aggregate_filter.rb +8 -10
  16. data/lib/double_entry/reporting/line_metadata_filter.rb +33 -0
  17. data/lib/double_entry/transfer.rb +33 -27
  18. data/lib/double_entry/validation.rb +1 -0
  19. data/lib/double_entry/validation/account_fixer.rb +36 -0
  20. data/lib/double_entry/validation/line_check.rb +22 -40
  21. data/lib/double_entry/version.rb +1 -1
  22. data/lib/generators/double_entry/install/install_generator.rb +7 -1
  23. data/lib/generators/double_entry/install/templates/migration.rb +27 -25
  24. metadata +33 -243
  25. data/.gitignore +0 -32
  26. data/.rspec +0 -2
  27. data/.travis.yml +0 -29
  28. data/.yardopts +0 -2
  29. data/Gemfile +0 -2
  30. data/Rakefile +0 -15
  31. data/script/jack_hammer +0 -210
  32. data/script/setup.sh +0 -8
  33. data/spec/active_record/locking_extensions_spec.rb +0 -110
  34. data/spec/double_entry/account_balance_spec.rb +0 -7
  35. data/spec/double_entry/account_spec.rb +0 -130
  36. data/spec/double_entry/balance_calculator_spec.rb +0 -88
  37. data/spec/double_entry/configuration_spec.rb +0 -50
  38. data/spec/double_entry/line_spec.rb +0 -80
  39. data/spec/double_entry/locking_spec.rb +0 -214
  40. data/spec/double_entry/performance/double_entry_performance_spec.rb +0 -32
  41. data/spec/double_entry/performance/reporting/aggregate_performance_spec.rb +0 -50
  42. data/spec/double_entry/reporting/aggregate_array_spec.rb +0 -123
  43. data/spec/double_entry/reporting/aggregate_spec.rb +0 -205
  44. data/spec/double_entry/reporting/line_aggregate_filter_spec.rb +0 -90
  45. data/spec/double_entry/reporting/line_aggregate_spec.rb +0 -39
  46. data/spec/double_entry/reporting/month_range_spec.rb +0 -139
  47. data/spec/double_entry/reporting/time_range_array_spec.rb +0 -169
  48. data/spec/double_entry/reporting/time_range_spec.rb +0 -45
  49. data/spec/double_entry/reporting/week_range_spec.rb +0 -103
  50. data/spec/double_entry/reporting_spec.rb +0 -181
  51. data/spec/double_entry/transfer_spec.rb +0 -93
  52. data/spec/double_entry/validation/line_check_spec.rb +0 -99
  53. data/spec/double_entry_spec.rb +0 -428
  54. data/spec/generators/double_entry/install/install_generator_spec.rb +0 -30
  55. data/spec/spec_helper.rb +0 -118
  56. data/spec/support/accounts.rb +0 -21
  57. data/spec/support/blueprints.rb +0 -43
  58. data/spec/support/database.example.yml +0 -21
  59. data/spec/support/database.travis.yml +0 -24
  60. data/spec/support/double_entry_spec_helper.rb +0 -27
  61. data/spec/support/gemfiles/Gemfile.rails-3.2.x +0 -8
  62. data/spec/support/gemfiles/Gemfile.rails-4.1.x +0 -6
  63. data/spec/support/gemfiles/Gemfile.rails-4.2.x +0 -5
  64. data/spec/support/gemfiles/Gemfile.rails-5.0.x +0 -5
  65. data/spec/support/performance_helper.rb +0 -26
  66. data/spec/support/reporting_configuration.rb +0 -6
  67. data/spec/support/schema.rb +0 -74
@@ -1,30 +0,0 @@
1
- require 'action_controller'
2
- require 'generator_spec/test_case'
3
- require 'generators/double_entry/install/install_generator'
4
-
5
- RSpec.describe DoubleEntry::Generators::InstallGenerator do
6
- include GeneratorSpec::TestCase
7
-
8
- destination File.expand_path('../../../../../tmp', __FILE__)
9
-
10
- before do
11
- prepare_destination
12
- run_generator
13
- end
14
-
15
- specify do
16
- expect(destination_root).to have_structure {
17
- directory 'db' do
18
- directory 'migrate' do
19
- migration 'create_double_entry_tables' do
20
- contains 'class CreateDoubleEntryTable'
21
- contains 'create_table "double_entry_account_balances"'
22
- contains 'create_table "double_entry_lines"'
23
- contains 'create_table "double_entry_line_aggregates"'
24
- contains 'create_table "double_entry_line_checks"'
25
- end
26
- end
27
- end
28
- }
29
- end
30
- end
@@ -1,118 +0,0 @@
1
- # encoding: utf-8
2
- require 'bundler/setup'
3
- require 'active_record'
4
- require 'active_support'
5
-
6
- if ActiveRecord::VERSION::MAJOR < 4
7
- require 'test-unit'
8
- Test::Unit::AutoRunner.need_auto_run = false
9
- end
10
-
11
- db_engine = ENV['DB'] || 'mysql'
12
-
13
- FileUtils.mkdir_p 'tmp'
14
- FileUtils.mkdir_p 'log'
15
- FileUtils.rm 'log/test.log', :force => true
16
-
17
- database_config_file = File.expand_path('../support/database.yml', __FILE__)
18
- if File.exist?(database_config_file)
19
- ActiveRecord::Base.establish_connection YAML.load_file(database_config_file)[db_engine]
20
- else
21
- puts 'Please configure your spec/support/database.yml file.'
22
- puts 'See spec/support/database.example.yml'
23
- exit 1
24
- end
25
-
26
- # Buffered Logger was deprecated in ActiveSupport 4.0.0 and was removed in 4.1.0
27
- # Logger was added in ActiveSupport 4.0.0
28
- if defined? ActiveSupport::Logger
29
- ActiveRecord::Base.logger = ActiveSupport::Logger.new('log/test.log')
30
- else
31
- ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new('log/test.log')
32
- end
33
-
34
- I18n.config.enforce_available_locales = false
35
-
36
- silence_warnings do
37
- require 'rspec'
38
- require 'rspec/its'
39
- require 'database_cleaner'
40
- require 'machinist/active_record'
41
- require 'timecop'
42
- require 'money'
43
- end
44
-
45
- require 'double_entry'
46
-
47
- Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
48
-
49
- RSpec.configure do |config|
50
- # rspec-expectations config goes here. You can use an alternate
51
- # assertion/expectation library such as wrong or the stdlib/minitest
52
- # assertions if you prefer.
53
- config.expect_with :rspec do |expectations|
54
- # This option will default to `true` in RSpec 4. It makes the `description`
55
- # and `failure_message` of custom matchers include text for helper methods
56
- # defined using `chain`, e.g.:
57
- # be_bigger_than(2).and_smaller_than(4).description
58
- # # => "be bigger than 2 and smaller than 4"
59
- # ...rather than:
60
- # # => "be bigger than 2"
61
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
62
- expectations.warn_about_potential_false_positives = false
63
- end
64
-
65
- # rspec-mocks config goes here. You can use an alternate test double
66
- # library (such as bogus or mocha) by changing the `mock_with` option here.
67
- config.mock_with :rspec do |mocks|
68
- # Prevents you from mocking or stubbing a method that does not exist on
69
- # a real object. This is generally recommended, and will default to
70
- # `true` in RSpec 4.
71
- mocks.verify_partial_doubles = true
72
- end
73
-
74
- # These two settings work together to allow you to limit a spec run
75
- # to individual examples or groups you care about by tagging them with
76
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
77
- # get run.
78
- config.filter_run :focus
79
- config.run_all_when_everything_filtered = true
80
-
81
- # Limits the available syntax to the non-monkey patched syntax that is recommended.
82
- # For more details, see:
83
- # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
84
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
85
- # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
86
- config.disable_monkey_patching!
87
-
88
- # Many RSpec users commonly either run the entire suite or an individual
89
- # file, and it's useful to allow more verbose output when running an
90
- # individual spec file.
91
- if config.files_to_run.one?
92
- # Use the documentation formatter for detailed output,
93
- # unless a formatter has already been configured
94
- # (e.g. via a command-line flag).
95
- config.default_formatter = 'doc'
96
- else
97
- config.default_formatter = 'RSpec::Instafail'
98
- end
99
-
100
- # Print the 5 slowest examples and example groups at the
101
- # end of the spec run, to help surface which specs are running
102
- # particularly slow.
103
- config.profile_examples = 5
104
-
105
- config.include DoubleEntrySpecHelper
106
-
107
- config.before(:suite) do
108
- DatabaseCleaner.strategy = :truncation
109
- end
110
-
111
- config.before do
112
- DatabaseCleaner.clean
113
- end
114
-
115
- config.after do
116
- Timecop.return
117
- end
118
- end
@@ -1,21 +0,0 @@
1
- # encoding: utf-8
2
- require_relative 'blueprints'
3
- DoubleEntry.configure do |config|
4
- # A set of accounts to test with
5
- config.define_accounts do |accounts|
6
- user_scope = accounts.active_record_scope_identifier(User)
7
- accounts.define(:identifier => :savings, :scope_identifier => user_scope, :positive_only => true)
8
- accounts.define(:identifier => :checking, :scope_identifier => user_scope, :positive_only => true)
9
- accounts.define(:identifier => :test, :scope_identifier => user_scope)
10
- accounts.define(:identifier => :btc_test, :scope_identifier => user_scope, :currency => 'BTC')
11
- accounts.define(:identifier => :btc_savings, :scope_identifier => user_scope, :currency => 'BTC')
12
- end
13
-
14
- # A set of allowed transfers between accounts
15
- config.define_transfers do |transfers|
16
- transfers.define(:from => :test, :to => :savings, :code => :bonus)
17
- transfers.define(:from => :test, :to => :checking, :code => :pay)
18
- transfers.define(:from => :savings, :to => :test, :code => :test_withdrawal)
19
- transfers.define(:from => :btc_test, :to => :btc_savings, :code => :btc_test_transfer)
20
- end
21
- end
@@ -1,43 +0,0 @@
1
- class UserBlueprint < Machinist::ActiveRecord::Blueprint
2
- def make!(attributes = {})
3
- savings_balance = attributes.delete(:savings_balance)
4
- checking_balance = attributes.delete(:checking_balance)
5
- bitcoin_balance = attributes.delete(:bitcoin_balance)
6
- user = super(attributes)
7
- if savings_balance
8
- DoubleEntry.transfer(
9
- savings_balance,
10
- :from => DoubleEntry.account(:test, :scope => user),
11
- :to => DoubleEntry.account(:savings, :scope => user),
12
- :code => :bonus,
13
- )
14
- end
15
- if checking_balance
16
- DoubleEntry.transfer(
17
- checking_balance,
18
- :from => DoubleEntry.account(:test, :scope => user),
19
- :to => DoubleEntry.account(:checking, :scope => user),
20
- :code => :pay,
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
31
- user
32
- end
33
- end
34
-
35
- class User < ActiveRecord::Base
36
- def self.blueprint_class
37
- UserBlueprint
38
- end
39
- end
40
-
41
- User.blueprint do
42
- username { "user#{sn}" }
43
- end
@@ -1,21 +0,0 @@
1
- postgres:
2
- host: localhost
3
- adapter: postgresql
4
- encoding: unicode
5
- database: double_entry_test
6
- pool: 100
7
- username: postgres
8
- password:
9
- min_messages: warning
10
- mysql:
11
- adapter: mysql2
12
- encoding: utf8
13
- database: double_entry_test
14
- pool: 100
15
- username: root
16
- password:
17
- sqlite:
18
- adapter: sqlite3
19
- encoding: utf8
20
- database: tmp/double_entry_test.sqlite3
21
- pool: 100
@@ -1,24 +0,0 @@
1
- mysql:
2
- adapter: mysql2
3
- username: root
4
- password:
5
- database: double_entry_test
6
- pool: 100
7
- timeout: 5000
8
- host: 127.0.0.1
9
-
10
- postgres:
11
- adapter: postgresql
12
- username: postgres
13
- password:
14
- database: double_entry_test
15
- min_messages: ERROR
16
- pool: 100
17
- timeout: 5000
18
- host: localhost
19
-
20
- sqlite:
21
- adapter: sqlite3
22
- encoding: utf8
23
- database: tmp/double_entry_test.sqlite3
24
- pool: 100
@@ -1,27 +0,0 @@
1
- # encoding: utf-8
2
- module DoubleEntrySpecHelper
3
- def lines_for_account(account)
4
- lines = DoubleEntry::Line.order(:id)
5
- lines = lines.where(:scope => account.scope_identity) if account.scoped?
6
- lines = lines.where(:account => account.identifier.to_s)
7
- lines
8
- end
9
-
10
- def perform_deposit(user, amount)
11
- DoubleEntry.transfer(
12
- Money.new(amount),
13
- :from => DoubleEntry.account(:test, :scope => user),
14
- :to => DoubleEntry.account(:savings, :scope => user),
15
- :code => :bonus,
16
- )
17
- end
18
-
19
- def perform_btc_deposit(user, amount)
20
- DoubleEntry.transfer(
21
- Money.new(amount, :btc),
22
- :from => DoubleEntry.account(:btc_test, :scope => user),
23
- :to => DoubleEntry.account(:btc_savings, :scope => user),
24
- :code => :btc_test_transfer,
25
- )
26
- end
27
- end
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '../../../'
4
-
5
- gem 'mysql2', '< 0.4'
6
- gem 'i18n', '0.6.11'
7
- gem 'rails', '~> 3.2.0'
8
-
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '../../../'
4
-
5
- gem 'mysql2', '< 0.4'
6
- gem 'rails', '~> 4.1.0'
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '../../../'
4
-
5
- gem 'rails', '~> 4.2.0'
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec :path => '../../../'
4
-
5
- gem 'rails', '~> 5.0.0'
@@ -1,26 +0,0 @@
1
- module PerformanceHelper
2
- require 'ruby-prof'
3
-
4
- def start_profiling(measure_mode = RubyProf::PROCESS_TIME)
5
- RubyProf.measure_mode = measure_mode
6
- RubyProf.start
7
- end
8
-
9
- def stop_profiling(profile_name = nil)
10
- result = RubyProf.stop
11
- puts "#{profile_name} Time: #{format('%#.3g', total_time(result))}s"
12
- unless ENV.fetch('CI', false)
13
- if profile_name
14
- outdir = './profiles'
15
- Dir.mkdir(outdir) unless Dir.exist?(outdir)
16
- printer = RubyProf::MultiPrinter.new(result)
17
- printer.print(:path => outdir, :profile => profile_name)
18
- end
19
- end
20
- result
21
- end
22
-
23
- def total_time(result)
24
- result.threads.inject(0) { |time, thread| time + thread.total_time }
25
- end
26
- end
@@ -1,6 +0,0 @@
1
- # encoding: utf-8
2
- RSpec.configure do |config|
3
- config.before do
4
- DoubleEntry::Reporting.instance_variable_set(:@configuration, nil)
5
- end
6
- end
@@ -1,74 +0,0 @@
1
- ActiveRecord::Schema.define do
2
- self.verbose = false
3
-
4
- create_table "double_entry_account_balances", :force => true do |t|
5
- t.string "account", :limit => 31, :null => false
6
- t.string "scope", :limit => 23
7
- t.integer "balance", :null => false
8
- t.timestamps :null => false
9
- end
10
-
11
- add_index "double_entry_account_balances", ["account"], :name => "index_account_balances_on_account"
12
- add_index "double_entry_account_balances", ["scope", "account"], :name => "index_account_balances_on_scope_and_account", :unique => true
13
-
14
- create_table "double_entry_lines", :force => true do |t|
15
- t.string "account", :limit => 31, :null => false
16
- t.string "scope", :limit => 23
17
- t.string "code", :limit => 47, :null => false
18
- t.integer "amount", :null => false
19
- t.integer "balance", :null => false
20
- t.integer "partner_id"
21
- t.string "partner_account", :limit => 31, :null => false
22
- t.string "partner_scope", :limit => 23
23
- t.integer "detail_id"
24
- t.string "detail_type"
25
- t.timestamps :null => false
26
- end
27
-
28
- add_index "double_entry_lines", ["account", "code", "created_at"], :name => "lines_account_code_created_at_idx"
29
- add_index "double_entry_lines", ["account", "created_at"], :name => "lines_account_created_at_idx"
30
- add_index "double_entry_lines", ["scope", "account", "created_at"], :name => "lines_scope_account_created_at_idx"
31
- add_index "double_entry_lines", ["scope", "account", "id"], :name => "lines_scope_account_id_idx"
32
-
33
- create_table "double_entry_line_aggregates", :force => true do |t|
34
- t.string "function", :limit => 15, :null => false
35
- t.string "account", :limit => 31, :null => false
36
- t.string "code", :limit => 47
37
- t.string "scope", :limit => 23
38
- t.integer "year"
39
- t.integer "month"
40
- t.integer "week"
41
- t.integer "day"
42
- t.integer "hour"
43
- t.integer "amount", :null => false
44
- t.string "filter"
45
- t.string "range_type", :limit => 15, :null => false
46
- t.timestamps :null => false
47
- end
48
-
49
- add_index "double_entry_line_aggregates", ["function", "account", "code", "year", "month", "week", "day"], :name => "line_aggregate_idx"
50
-
51
- create_table "double_entry_line_checks", :force => true do |t|
52
- t.integer "last_line_id", :null => false
53
- t.boolean "errors_found", :null => false
54
- t.text "log"
55
- t.timestamps :null => false
56
- end
57
-
58
- create_table "double_entry_line_metadata", :force => true do |t|
59
- t.integer "line_id", :null => false
60
- t.string "key", :limit => 48, :null => false
61
- t.string "value", :limit => 64, :null => false
62
- t.timestamps :null => false
63
- end
64
-
65
- add_index "double_entry_line_metadata", ["line_id", "key", "value"], :name => "lines_meta_line_id_key_value_idx"
66
-
67
- # test table only
68
- create_table "users", :force => true do |t|
69
- t.string "username", :null => false
70
- t.timestamps :null => false
71
- end
72
-
73
- add_index "users", ["username"], :name => "index_users_on_username", :unique => true
74
- end