GithubHelp home page GithubHelp logo

envato / double_entry Goto Github PK

View Code? Open in Web Editor NEW
408.0 83.0 69.0 734 KB

A double-entry accounting system for Ruby applications.

Home Page: https://rubygems.org/gems/double_entry

License: MIT License

Ruby 98.89% Shell 0.14% Logos 0.63% Dockerfile 0.34%
finance ruby gem accounting

double_entry's People

Contributors

achhetr avatar andyjdavis avatar brewdium avatar dersnek avatar doncote avatar eadz avatar elct9620 avatar fesplugas avatar gja avatar jacobbednarz avatar jiexinhuang avatar kelseydh avatar orien avatar rabidcarrot avatar ricobl avatar rizalmuthi avatar ryanzhou avatar salamagd avatar scottyp-env avatar sj26 avatar spacepotato avatar spickermann avatar stavro avatar stephnacios avatar stevend avatar swrobel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

double_entry's Issues

Why does #lock_tables need to be the outermost transaction?

Consider the following code:

class Invoice::Payer
  # ...

  def pay
    @invoice.lock do
      payment = CreditCard::Charger.charge(@invoice.account.credit_card, @invoice.description, @invoice.amount)
      if payment.success?
        @invoice.update(paid: true)
      end
    end
  end
end

class CreditCard::Charger
  # ...

  def charge
    # ...

    from_account = DoubleEntry.account(:credit_card, scope: @credit_card.account)
    to_account = DoubleEntry.account(:sales, scope: @credit_card.account)

    DoubleEntry.transfer(@amount, from: from_account, to: to_account, code: :purchase)
  end
end

This seems like pretty reasonable code to me, but unfortunately doesn't work because in the Invoice class, I'm locking the invoice (which creates a transaction), and then the DoubleEntry#transfer method fails because it's transaction is not the outer-most one.

What's the reasoning behind making it the outer-most transaction? What would the world be like if it "just worked"?

Support Multiple Currencies per Account

Currently, an Account has a configured currency associated to it.
As I understand it, the currency is fixed and enforced for all transfers involving the account.
For our use-case, we'd like to be able to have a single account identifier (ie. :cash, :vendor_payable, etc.) to support multiple currencies.

To clarify, only a single currency would be involved in a transaction.
For example:

vendor = Vendor.take # Some vendor
order  = vendor.orders.payable.first # Some order from the vendor

cash           = DoubleEntry.account(:cash, currency: order.currency)
vendor_payable = DoubleEntry.account(:vendor_payable, currency: order.currency, scope: vendor)

DoubleEntry.transfer(order.vendor_total, from: cash, to: vendor_payable, code: :pay_vendor_for_order)

Essentially, account(:cash, currency: 'CAD') would hold a separate balance from account(:cash, currency: 'USD').

In terms of technical changes required to accomplish this, it looks to be just a matter of adding a currency column to the double_entry_lines table, and scoping queries for Line records by currency (for calculating balances and the like).

While this could be accomplished by defining many different versions of each account (:cash_cad, :cash_usd, :cash_sek, :cash_eur, etc.), it would considerably complicate displaying breakdowns and balances to the internal and end users, and also force all possible transfers to be configured N times (once per currency).

Un-scoped accounts are not sortable, fail <=> against scoped accounts.

Just wondering what the suggested way to handle a global account is, i.e. an account that is not scoped to an object. We had started with a global account... accounts.define(identifier: :global) but that fails <=>.

Our idea was:
Payins => Payments => Global => Earnings => Payouts
With global acting as a buffer and also retaining our platform profits.

My understanding is that any double entry transfer has to come from or go to somewhere, so in our setup Payins (credit card transfers) would always be negative and Payouts (to external bank account) would always be positive.

Thanks for the help!

Wrong dates in changelog

I just noticed that the dates in the changelog for releases [2.0.0.beta4] and [2.0.0.beta5] are probably not correct and are actually much more recent according to a "git blame". Just thought you might want to correct that. Many thanks :)

Use bigint for all IDs

integer is currently being used, and it took our project only a few months to hit more transactions than the 32 bit int supports. I'd suggest changing all IDs to bigint.

DoubleEntry.balance uses Line rather than AccountBalance

This doesn't seem like the most efficient way to go about things, considering there's a table just to store account balances. Am I missing something?

def balance(account, options = {})
  account = account(account, options) if account.is_a? Symbol
  BalanceCalculator.calculate(account, options)
end

should be, imho:

def balance(account, options = {})
  account = account(account, options) if account.is_a? Symbol
  AccountBalance.find_by_account(account).balance
end

Make detail association optional in DoubleEntry::Line

Do the library enforce the presence of :detail option in DoubleEntry.transfer? If not, please make the detail association in DoubleEntry::Line optional, because Rails 5 makes belongs_to association required by default.

Migration fails because of duplicate detail fields in double_entry_lines

Steps to reproduce

Install gem with

gem "double_entry", github: "envato/double_entry"

Run

bundle install

Run

rails generate double_entry:install

Run

rails db:migrate

Expected result:
Migration should run successfully, adding required tables.

Actual result:
Migration fails with the following

== 20191106104924 CreateDoubleEntryTables: migrating ==========================
-- create_table("double_entry_account_balances", {:force=>true})
   -> 0.0392s
-- add_index("double_entry_account_balances", ["account"], {:name=>"index_account_balances_on_account"})
   -> 0.0176s
-- add_index("double_entry_account_balances", ["scope", "account"], {:name=>"index_account_balances_on_scope_and_account", :unique=>true})
   -> 0.0203s
-- create_table("double_entry_lines", {:force=>true})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

you can't define an already defined column 'detail_id'.
...
.../db/migrate/20191106104924_create_double_entry_tables.rb:23:in `block in up'
...

Caused by:
ArgumentError: you can't define an already defined column 'detail_id'.
...
.../db/migrate/20191106104924_create_double_entry_tables.rb:23:in `block in up'
...

Exactly the same problem happens with detail_type field in the same table.

Reason

On migration from integers to bigints, the following line was added:

t.references "detail", :index => false, :polymorphic => true

However, these lines weren't removed:

t.integer    "detail_id"
t.string     "detail_type"

So detail reference now looks like this in migration:

t.references "detail", :index => false, :polymorphic => true
t.integer    "detail_id"
t.string     "detail_type"

These are duplicate lines and they cause the problem.

Added:
If I remove these two lines, migration runs successfully.

Support UUID Model ids

UUID's are a popular strategy for model id's due to their unique properties across all tables. Unfortunately it appears that this gem does not support uuid's natively, owing to a 17 strong character letter limit on scope objects id.

This can be seen with the following test, which will fail:

    it 'finds account by uuid' do
      object_with_uuid = double(:id => 'fea45df8-2ec0-4e8d-9c5a-5871a5414bca')

      expect do
        DoubleEntry.account(:savings, :scope => object_with_uuid)
      end.to_not raise_error

      expect do
        DoubleEntry.balance(:savings, :scope => object_with_uuid)
      end.to_not raise_error
    end

Which if run will result in this failure showing the problem:

=>      Failure/Error:
       expect do
         DoubleEntry.account(:savings, :scope => object_with_uuid)
       end.to_not raise_error
     
       expected no Exception, got #<DoubleEntry::ScopeIdentifierTooLongError: scope identifier 'fea45df8-2ec0-4e8d-9c5a-5871a5414bca' is too long. Please limit it to 23 characters.> 

with backtrace:
         # ./lib/double_entry/account.rb:167:in `ensure_scope_is_valid'
         # ./lib/double_entry/account.rb:108:in `initialize'
         # ./lib/double_entry/account.rb:27:in `new'
         # ./lib/double_entry/account.rb:27:in `account'
         # ./lib/double_entry.rb:44:in `account'
         # ./spec/double_entry_spec.rb:417:in `block (4 levels) in <top (required)>'
         # ./spec/double_entry_spec.rb:416:in `block (3 levels) in <top (required)>'
     # ./spec/double_entry_spec.rb:416:in `block (3 levels) in <top (required)>'

Instead, double_entry implemention should support both sequential ids and uuid's -- the big benefit with UUID's being we no longer need to worry about the validity of id values and what model its associated with. This makes it easy to use double_entry in outside contexts, like consuming the ledgers of external systems where account objects are represented as api keys or other arbitrary string values.

Why do balances become incorrect?

Generally speaking, why do we need to run the account fixer/checker, and how often should we run it?

I just ran it today, and it found probably 20-30 calculation errors made over the past few months. I'm just curious what situations generally cause these balance miscalculations? Thanks for the awesome library btw!

Version 2.0 release

Is there anything blocking for version 2.0 release. It has been more than a year for beta version.

DoubleEntry::TransferNotAllowed between accounts with different scope (but same identifier)

I defined a primary account like so:

config.define_accounts do |accounts|
    user_scope = ->(user) do
      raise 'not a User' unless user.class.name == 'User'
      user.id
    end
    
    accounts.define(identifier: :primary, scope_indentifier: user_scope, ...)
end

And a transfer transfer like so:

config.define_transfers do |transfers|
    transfers.define(from: :primary, to: :primary, code: :transfer)
end

If I try to do a transfer like this:

user1 = User.first
user2 = User.last

account1 = DoubleEntry.account(:primary, scope: user1.id)
account2 = DoubleEntry.account(:primary, scope: user2.id)

DoubleEntry.transfer(Money.new(1),
                     from: account1,
                     to: account2,
                     code: :transfer)

It throws a DoubleEntry::TransferNotAllowed. This strikes me as weird behaviour. They don't have the same scope/user. Users should be able to move money between each other's accounts.

I did some further digging and found that both account1.scope_identity and account2.scope_identity return the same User id.

Can't seem to figure out why.

Infinite loop for TimeRangeArray#make over daylight savings time

Master branch is currently unable to perform any reporting on a day or hour granularity over a time period that includes daylight savings time.

Example: (set computer time to America/Los_Angeles)

DoubleEntry::Reporting.aggregate_array(
  :sum,
  :checking,
  :save,
  :range_type => 'day',
  :start      => '2014-01-01',
  :finish     => '2014-12-31',
)

This results in an infinite loop within the #make method, due to line 19.

After deeper inspection, the culprit is invalid date calculation in DayRange#from_time.

DoubleEntry::Reporting::DayRange.from_time(Time.parse('2014, Sun Mar 09')).next.to_s
=> "2014, Mon Mar 03"

Rails 5 issue: Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Rails release the migration was written for:

StandardError: An error has occurred, this and all later migrations canceled:

Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Rails release the migration was written for:

  class CreateDoubleEntryTables < ActiveRecord::Migration[4.2]
/APP_NAME/db/migrate/20171128034808_create_double_entry_tables.rb:1:in `<top (required)>'
/APP_NAME/config/initializers/task.rb:7:in `execute'

As the error message recommends, I was able to fix this for Rails 5 by specifying the correct version in the migration (currently it just outputs class CreateDoubleEntryTables < ActiveRecord::Migration).

This seems like an easy PR to bring in, and would prevent people from shooting themselves in the foot when adding this gem for the first time.

Support Rails 7

Hi,

When I trying to use it with Rails 7. I get following errors.

rails aborted!
StandardError: Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Active Record release the migration was written for:

  class CreateDoubleEntryTables < ActiveRecord::Migration[7.0]
/Users/zoloo/code/lawmax-web/db/migrate/20220620000008_create_double_entry_tables.rb:1:in `<main>'

Caused by:
StandardError: Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Active Record release the migration was written for:

  class CreateDoubleEntryTables < ActiveRecord::Migration[7.0]
/Users/zoloo/code/lawmax-web/db/migrate/20220620000008_create_double_entry_tables.rb:1:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace

It's looks like not support Rails 7.

Money.infinite_precision is deprecated

Hey! It looks like money gem changed something inside and log files are full of

[DEPRECATION] Money.infinite_precision is deprecated - use Money.default_infinite_precision instead.

Any plans on fixing it?

Positive Only does not work with concurrent calls

I have a ledger running with an account type set to positive_only true. See the Wallet account type in the following:

https://github.com/sudhirj/notecase/blob/master/config/initializers/double_entry.rb

This works fine normally, but on a very small minority of cases where transactions come in at almost the same time, I've seen account balances go negative. Is there anything that can be done to avoid this? Both accounts are being locked as follows:

https://github.com/sudhirj/notecase/blob/master/app/models/transaction.rb

Any ideas on how we can improve the integrity of positive_only accounts?

Store `DoubleEntry::Line#scope` as integer

The attribute DoubleEntry::Line#scope is currently stored as a VARCHAR. The use case for this attribute is to link to some business entity. Therefore the column type should be INTEGER; identical to how ActiveRecord IDs are stored.

Can't run tests because of SyntaxError

I've cloned master branch, done everything mentioned in Development Environment Setup, but when I try to run tests with:

bundle exec rake

I get the following error:

Running tests with `DB=mysql`
/home/mark/.rvm/rubies/ruby-2.2.10/bin/ruby -I/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/rspec-core-3.9.0/lib:/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/rspec-support-3.9.0/lib /home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/rspec-core-3.9.0/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/rates_store/memory.rb:103: warning: private attribute?
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/rates_store/memory.rb:103: warning: private attribute?
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/money/formatting_rules.rb:29: warning: private attribute?
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/money/formatter.rb:250: warning: private attribute?
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/money/formatter.rb:250: warning: private attribute?
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/money/formatter.rb:250: warning: private attribute?
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/money.rb:146: warning: method redefined; discarding old locale_backend=
/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/money-6.13.4/lib/money/money.rb:150: warning: method redefined; discarding old use_i18n=
/home/mark/code/opensource/double_entry/lib/double_entry/validation/line_check.rb:97: warning: `<<' after local variable or literal is interpreted as binary operator
/home/mark/code/opensource/double_entry/lib/double_entry/validation/line_check.rb:97: warning: even though it seems like here document

An error occurred while loading spec_support.
Failure/Error: require 'double_entry/validation/line_check'

SyntaxError:
  /home/mark/code/opensource/double_entry/lib/double_entry/validation/line_check.rb:97: syntax error, unexpected <<
            log << <<~MESSAGE unless correct
                     ^
  /home/mark/code/opensource/double_entry/lib/double_entry/validation/line_check.rb:98: syntax error, unexpected **arg, expecting keyword_end
              *********************************
                ^
  /home/mark/code/opensource/double_entry/lib/double_entry/validation/line_check.rb:100: syntax error, unexpected **arg, expecting keyword_end
              *********************************
                ^
  /home/mark/code/opensource/double_entry/lib/double_entry/validation/line_check.rb:102: dynamic constant assignment
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require'
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `block in require'
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:257:in `load_dependency'
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require'
# ./lib/double_entry/validation.rb:2:in `<top (required)>'
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require'
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `block in require'
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:257:in `load_dependency'
# ./.bundle/ruby/2.2.0/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require'
# ./lib/double_entry.rb:19:in `<top (required)>'
# ./spec/spec_support.rb:1:in `require'
# ./spec/spec_support.rb:1:in `<top (required)>'
No examples found.


Finished in 0.00004 seconds (files took 0.55766 seconds to load)
0 examples, 0 failures, 1 error occurred outside of examples

/home/mark/.rvm/rubies/ruby-2.2.10/bin/ruby -I/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/rspec-core-3.9.0/lib:/home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/rspec-support-3.9.0/lib /home/mark/code/opensource/double_entry/.bundle/ruby/2.2.0/gems/rspec-core-3.9.0/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb failed

Reporting Bug

Im looking into reporting, I think there is a bug in reconciled?:

scoped_lines = Line.where(:account => "#{account.identifier}", :scope => "#{account.scope}")

Should be:

scoped_lines = Line.where(:account => "#{account.identifier}", :scope => "#{account.scope.id}")

Also, to generate a ledger should I just be querying DoubleEntry::Line directly, or is there a method existing for that?

Thanks!

A better way of defining the scope lambda

The documentation includes with example of defining a scope lambda:

    user_scope = lambda do |user_identifier|
      if user_identifier.is_a?(User)
        user_identifier.id
      else
        user_identifier
      end
    end

Let's implement a generic version of this. It should include some sweet syntactic sugar for easy use in Double Entry configuration.

DoubleEntry::UnknownAccount: account: spending scoped?: true

On a Rails 5.1.4 app installing double_entry using Postgresql, with the following initializer:

require 'double_entry'

DoubleEntry.configure do |config|
  config.define_accounts do |accounts|
    user_scope = accounts.active_record_scope_identifier(User)
    accounts.define(:identifier => :savings,  :scope_identifier => user_scope, :positive_only => true)
    accounts.define(:identifier => :checking, :scope_identifier => user_scope)
  end

  config.define_transfers do |transfers|
    transfers.define(:from => :checking, :to => :savings,  :code => :deposit)
    transfers.define(:from => :savings,  :to => :checking, :code => :withdraw)
  end
end 

and unchanged migrations (beyond specifying ActiveRecord version 5.1).

I get the following error in console:

=> account = DoubleEntry.account(:spending, :scope => User.first)
  User Load (0.3ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
DoubleEntry::UnknownAccount: account: spending scoped?: true

Is this possibly related to #115? I've tried every combination I can think of for passing in a scope here and it's all failing.

My app already has an Account and Transfer model defined, but surely this shouldn't be of issue given double_entry's module namespacing? Any help much appreciated.

Lack of negative_only account option

We have the positive_only account option, but lack a negative_only option.

For our use-case, a negative_only account option and complementary validation would be quite beneficial.

Remove `DoubleEntry::Line#meta`

The need to store business meta data in each line is dubious. The implementation, marshalling the object to a textual column, brittle. The attribute meta should be removed.

The use case of associating business events to a monetary transfer is satisfied by the polymorphic association of DoubleEntry::Line#detail.

Rails 6.1.X Compatibility?

Are there plans to add Rails 6.1.X compatibility? I can raise a PR like #176, assuming there aren't any major problems with Rails 6.1.

Thanks!

Dynamic accounts

Would you recommend using this as a base for an app that will have dynamic accounts? i.e. users creating accounts

Incorrect identifier checking for balance queries

DoubleEntry#balance does not properly check the scope type.

Example configuration:

Assume 2 active record models, User, and Bank

DoubleEntry.configure do |config|
  config.define_accounts do |accounts|
    user_scope = accounts.active_record_scope_identifier(User)
    accounts.define(:identifier => :cash, :scope_identifier => user_scope)

    bank_scope = accounts.active_record_scope_identifier(Bank)
    accounts.define(:identifier => :piggybank, :scope_identifier => bank_scope)
  end

  config.define_transfers do |transfers|
    transfers.define(:from => :cash, :to => :piggybank,  :code => :deposit)
  end
end

Initial transfer:

cash_account = DoubleEntry.account(:cash, scope: User.new(id: 1))
bank_account = DoubleEntry.account(:piggybank, scope: Bank.new(id: 1))

DoubleEntry.transfer(Money.new(100), from: cash_account, to: bank_account, :code => :deposit)

Balance queries:

DoubleEntry.account(:cash, scope: User.new(id: 1)).balance  #=> CORRECT (-100)
DoubleEntry.balance(:cash, scope: User.new(id: 1)) #=> CORRECT (-100)

DoubleEntry.account(:cash, scope: Bank.new(id: 1)).balance #=> CORRECT(0) (Banks should not have :cash accounts)
DoubleEntry.balance(:cash, scope: Bank.new(id: 1)) #=> ***** INCORRECT (-100) *****

Accounting rules

What do you mean by this program does not enforce accounting rules?

Importing Legacy Transactions

Does anyone have a good pattern for importing legacy transactions into DE? This would require recording a transfer at a specific time in the past.

It looks like there are two options:

  1. Modifications to transfer/process/create_lines in order to override default dates

  2. Override Time.now or AR setters for created_at/updated_at in a block outside the transfer creation.

Any ideas, thoughts, gists welcome.

AccountScopeMismatchError after an error

Hi!,
I'm getting this error:

DoubleEntry::AccountScopeMismatchError (Expected instance of `User`, received instance of `User`)

every time I made an error in a method using DoubleEntry (even if the error is not DoubleEntry related). This happens in the console and the server, and the only solution is killing the server, restarting the console, and killing Spring.
I'm still using DoubleEntry in development, but I'm very afraid that the issue will cause a lot of trouble in production. Even using this #75 (comment) the issue remains.

Here's a more detailed example:
(everything works fine, on purpose delete a comma in a Hash)

SyntaxError (app/controllers/cartolas_controller.rb:16: syntax error, unexpected tIDENTIFIER, expecting ')'
...eEntry.account(:cilindros scope: x)}}
...                               ^
app/controllers/cartolas_controller.rb:23: syntax error, unexpected keyword_end, expecting '}'
app/controllers/cartolas_controller.rb:57: syntax error, unexpected keyword_end, expecting '}'):
  app/controllers/cartolas_controller.rb:16: syntax error, unexpected tIDENTIFIER, expecting ')'
  app/controllers/cartolas_controller.rb:23: syntax error, unexpected keyword_end, expecting '}'
  app/controllers/cartolas_controller.rb:57: syntax error, unexpected keyword_end, expecting '}'


  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_source.erb (5.4ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_trace.html.erb (2.5ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_request_and_response.html.erb (1.3ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/_web_console.html.erb (1.0ms)
  Rendered /Users/marcelo/.rvm/gems/ruby-2.2-head@bo_distribuidores/gems/web-console-2.0.0/lib/action_dispatch/templates/rescues/diagnostics.html.erb within rescues/layout (171.4ms)

Fixing the error, making the same request:

Started GET "/cartolas" for 127.0.0.1 at 2016-05-06 11:27:06 -0400
Processing by CartolasController#index as HTML
[...]
DoubleEntry::AccountScopeMismatchError (Expected instance of `User`, received instance of `User`):
  app/controllers/cartolas_controller.rb:13:in `block in index'
  app/controllers/cartolas_controller.rb:13:in `index'

Only restarting the servers everything is back to normal.

Please help me!!!

AccountFixer not fix account which scope is nil

Hi, the LineCheck can find the accounts which scope: nil but the AccountFixer didn't fix it correctly.

def lines_for_account(account)
Line.where(
account: account.identifier.to_s,
scope: account.scope_identity.to_s
).order(:id)
end

The line scope: account.scope_identity.to_s always convert nil to "" (empty string) that it unable find correct account lines to update balance.

Possible Options:

  1. Change scope: account.scope_identity.to_s to scope: account.scope_identity&.to_s
  2. Set scope column default to "" instead accept nil

We may consider to the unscoped account in this case if we set all scope to "" instead of nil

Updated

Due to the LineCheck SQL, option 1 will unable to find any Line in this case

previous_line = Line.find_by_sql([<<-SQL, line.account.identifier.to_s, line.scope, line.id])
SELECT * FROM #{Line.quoted_table_name} #{force_index}
WHERE account = ?
AND scope = ?
AND id < ?
ORDER BY id DESC
LIMIT 1
SQL

In this case, the scope = NULL is not working correctly.

My database is PostgreSQL and not sure how MySQL works in this case.

Note

Sometimes one of my accounts which without scope will reset the balance to 0 after the transfer (eg. from 100.0 to 1.0)

But if the LineCheck works correctly, the balance can go back correctly value.

I am not sure the relationship between the above two issues, but it seems we have some problems when using scope if it is nil?

Scopes don't support UUIDs

Because of the 23 character limit, it looks like it's impossible to support UUIDs as scopes - this is quite odd because they make excellent scopes. Can we do something about this?

ActiveRecord deprecation

I got this deprecation warning when executed DoubleEntry::Validation::LineCheck.perform!

DEPRECATION WARNING: Using `return`, `break` or `throw` to exit a transaction block is
deprecated without replacement. If the `throw` came from
`Timeout.timeout(duration)`, pass an exception class as a second
argument so it doesn't use `throw` to abort its block. This results
in the transaction being committed, but in the next release of Rails
it will raise and rollback.
 (called from restartable_transaction at lib/ruby/gems/2.5.0/bundler/gems/double_entry-4ee0d7f9707a/lib/active_record/locking_extensions.rb:10)

I use newest rails

Need more understand to run LineCheck.perform!

Hi, I still don't know what the function of LineCheck.perform!, I know if the documentation already complete but I still don't get it when and where this function is needed.

So let say I'm a hacker and I run in rails console, and I manipulate the transaction directly to the database and The system will automaticly fix that? or something else?

Please, anyone, tell the simple case to use this function?

# Check all accounts & write the results to the double_entry_line_checks table
DoubleEntry::Validation::LineCheck.perform!

# Check & fix accounts (results will also be written to the table)
DoubleEntry::Validation::LineCheck.perform!(fixer: DoubleEntry::Validation::AccountFixer.new)

For now, I haven't created a background scheduler yet to use that function, I think It isn't complete yet

Allow validation on transfer definition

For my project I needed some sort of additional check when I defined transfers.

Something like this:

transfers.define(from: :savings,  to: :checking, code: :withdraw) do |from, to|
  if from.scope.blocked?
    fail DoubleEntry::TransferNotAllowed, 'user is blocked'
  end
end

I monkey patched gem and would like to make a PR if you think it's worth to have.

Here's my monkey patch:

# frozen_string_literal: true

module OverrideDefineMethod
  def define(attributes, &block)
    attributes.merge!(block: block) if block_given?
    super(attributes)
  end

  def find!(from_account, to_account, code)
    transfer = super
    transfer.block.call(from_account, to_account) if transfer.block
    transfer
  end
end

module OverrideTransferInitializer
  attr_reader :block

  def initialize(attributes)
    @block = attributes[:block]
    super(attributes)
  end
end

DoubleEntry::Transfer::Set.prepend OverrideDefineMethod
DoubleEntry::Transfer.prepend OverrideTransferInitializer

DoubleEntry.transfer returns nil

DoubleEntry.transfer always returns nil.

I think it'd be more useful if it returns the credit & debit lines like the create_lines method does.
Is there any reason it returns nil?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.