double_double 0.0.1
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.
- data/.gitignore +18 -0
- data/.rspec +3 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +10 -0
- data/double_double.gemspec +27 -0
- data/lib/double_double/account.rb +85 -0
- data/lib/double_double/amount.rb +33 -0
- data/lib/double_double/asset.rb +25 -0
- data/lib/double_double/credit_amount.rb +9 -0
- data/lib/double_double/debit_amount.rb +9 -0
- data/lib/double_double/equity.rb +26 -0
- data/lib/double_double/expense.rb +26 -0
- data/lib/double_double/liability.rb +25 -0
- data/lib/double_double/revenue.rb +26 -0
- data/lib/double_double/transaction.rb +88 -0
- data/lib/double_double/transaction_type.rb +13 -0
- data/lib/double_double/version.rb +3 -0
- data/lib/double_double.rb +21 -0
- data/spec/factories/account_factory.rb +27 -0
- data/spec/factories/amount_factory.rb +10 -0
- data/spec/factories/transaction_factory.rb +9 -0
- data/spec/factories/transaction_type_factory.rb +14 -0
- data/spec/models/account_spec.rb +70 -0
- data/spec/models/amount_spec.rb +9 -0
- data/spec/models/asset_spec.rb +12 -0
- data/spec/models/credit_amount_spec.rb +46 -0
- data/spec/models/debit_amount_spec.rb +46 -0
- data/spec/models/equity_spec.rb +12 -0
- data/spec/models/expense_spec.rb +12 -0
- data/spec/models/liability_spec.rb +12 -0
- data/spec/models/revenue_spec.rb +12 -0
- data/spec/models/transaction_spec.rb +101 -0
- data/spec/spec_helper.rb +87 -0
- data/spec/support/all_account_types.rb +50 -0
- data/spec/support/left_side_account_types.rb +125 -0
- data/spec/support/right_side_account_types.rb +125 -0
- metadata +216 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Mike Herrera
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# double_double
|
2
|
+
[](https://travis-ci.org/crftr/double_double)
|
3
|
+
|
4
|
+
A double-entry accounting system. Likely to change heavily in the coming days.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'double_double'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install double_double
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
TODO: Write usage instructions here
|
23
|
+
|
24
|
+
## Name
|
25
|
+
|
26
|
+
The double double is the flagship In-N-Out cheeseburger. Ask a southern-Californian.
|
27
|
+
|
28
|
+
## Contributing
|
29
|
+
|
30
|
+
1. Fork it
|
31
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
32
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
33
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
34
|
+
5. Create new Pull Request
|
35
|
+
|
36
|
+
## Notes
|
37
|
+
|
38
|
+
double_double was heavily influenced by mbulat's plutus project and regularly working with quickbooks.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'double_double/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'double_double'
|
8
|
+
gem.version = DoubleDouble::VERSION
|
9
|
+
gem.authors = ['Mike Herrera']
|
10
|
+
gem.email = ['git@devoplabs.com']
|
11
|
+
gem.description = %q{A double-entry accural accounting system}
|
12
|
+
gem.summary = %q{A double-entry accural accounting system. All currency amounts are stored using the Money gem.}
|
13
|
+
gem.homepage = 'https://github.com/crftr/double_double'
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features|account_types)/})
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
|
20
|
+
gem.add_dependency('money', '~> 5.1')
|
21
|
+
gem.add_dependency 'activerecord', '~> 3.2.11'
|
22
|
+
gem.add_development_dependency('sqlite3')
|
23
|
+
gem.add_development_dependency('rspec', '~> 2.12')
|
24
|
+
gem.add_development_dependency('factory_girl')
|
25
|
+
gem.add_development_dependency('database_cleaner')
|
26
|
+
gem.add_development_dependency('pry')
|
27
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# The Account class represents accounts in the system. Each account must be subclassed as one of the following types:
|
3
|
+
#
|
4
|
+
# TYPE | NORMAL BALANCE | DESCRIPTION
|
5
|
+
# --------------------------------------------------------------------------
|
6
|
+
# Asset | Debit | Resources owned by the Business Entity
|
7
|
+
# Liability | Credit | Debts owed to outsiders
|
8
|
+
# Equity | Credit | Owners rights to the Assets
|
9
|
+
# Revenue | Credit | Increases in owners equity
|
10
|
+
# Expense | Debit | Assets or services consumed in the generation of revenue
|
11
|
+
#
|
12
|
+
# Each account can also be marked as a "Contra Account". A contra account will have it's
|
13
|
+
# normal balance swapped. For example, to remove equity, a "Drawing" account may be created
|
14
|
+
# as a contra equity account as follows:
|
15
|
+
#
|
16
|
+
# DoubleDouble::Equity.create(:name => "Drawing", contra => true)
|
17
|
+
#
|
18
|
+
# At all times the balance of all accounts should conform to the "accounting equation"
|
19
|
+
# DoubleDouble::Assets = Liabilties + Owner's Equity
|
20
|
+
#
|
21
|
+
# Each sublclass account acts as it's own ledger. See the individual subclasses for a
|
22
|
+
# description.
|
23
|
+
#
|
24
|
+
# @abstract
|
25
|
+
# An account must be a subclass to be saved to the database. The Account class
|
26
|
+
# has a singleton method {trial_balance} to calculate the balance on all Accounts.
|
27
|
+
#
|
28
|
+
# @see http://en.wikipedia.org/wiki/Accounting_equation Accounting Equation
|
29
|
+
# @see http://en.wikipedia.org/wiki/Debits_and_credits Debits, Credits, and Contra Accounts
|
30
|
+
#
|
31
|
+
class Account < ActiveRecord::Base
|
32
|
+
self.table_name = 'double_double_accounts'
|
33
|
+
|
34
|
+
attr_accessible :name, :contra, :number
|
35
|
+
|
36
|
+
has_many :credit_amounts
|
37
|
+
has_many :debit_amounts
|
38
|
+
has_many :credit_transactions, :through => :credit_amounts, :source => :transaction
|
39
|
+
has_many :debit_transactions, :through => :debit_amounts, :source => :transaction
|
40
|
+
|
41
|
+
validates_presence_of :type, :name, :number
|
42
|
+
validates_uniqueness_of :name, :number
|
43
|
+
|
44
|
+
def side_balance(is_debit, hash)
|
45
|
+
a = is_debit ? DoubleDouble::DebitAmount.scoped : DoubleDouble::CreditAmount.scoped
|
46
|
+
a = a.where(account_id: self.id)
|
47
|
+
a = a.by_project_id( hash[:project_id] ) if hash.has_key?(:project_id)
|
48
|
+
a = a.by_approving_user_id( hash[:approving_user_id] ) if hash.has_key?(:approving_user_id)
|
49
|
+
a = a.by_targeted_user_id( hash[:targeted_user_id] ) if hash.has_key?(:targeted_user_id)
|
50
|
+
Money.new(a.sum(:amount_cents))
|
51
|
+
end
|
52
|
+
|
53
|
+
def credits_balance(hash = {})
|
54
|
+
side_balance(false, hash)
|
55
|
+
end
|
56
|
+
|
57
|
+
def debits_balance(hash = {})
|
58
|
+
side_balance(true, hash)
|
59
|
+
end
|
60
|
+
|
61
|
+
# The trial balance of all accounts in the system. This should always equal zero,
|
62
|
+
# otherwise there is an error in the system.
|
63
|
+
#
|
64
|
+
# @return [Money] The value balance of all accounts
|
65
|
+
def self.trial_balance
|
66
|
+
raise(NoMethodError, "undefined method 'trial_balance'") unless self.new.class == DoubleDouble::Account
|
67
|
+
Asset.balance - (Liability.balance + Equity.balance + Revenue.balance - Expense.balance)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.balance
|
71
|
+
raise(NoMethodError, "undefined method 'balance'") if self.new.class == DoubleDouble::Account
|
72
|
+
accounts_balance = Money.new(0)
|
73
|
+
accounts = self.all
|
74
|
+
accounts.each do |acct|
|
75
|
+
if acct.contra
|
76
|
+
accounts_balance -= acct.balance
|
77
|
+
else
|
78
|
+
accounts_balance += acct.balance
|
79
|
+
end
|
80
|
+
end
|
81
|
+
accounts_balance
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# The Amount class represents debit and credit amounts in the system.
|
3
|
+
#
|
4
|
+
# @abstract
|
5
|
+
# An amount must be a subclass as either a debit or a credit to be saved to the database.
|
6
|
+
#
|
7
|
+
class Amount < ActiveRecord::Base
|
8
|
+
self.table_name = 'double_double_amounts'
|
9
|
+
|
10
|
+
attr_accessible :account, :amount, :transaction, :project_id, :approving_user_id, :targeted_user_id
|
11
|
+
|
12
|
+
belongs_to :transaction
|
13
|
+
belongs_to :account
|
14
|
+
belongs_to :project
|
15
|
+
belongs_to :approving_user, :class_name => "User"
|
16
|
+
belongs_to :targeted_user, :class_name => "User"
|
17
|
+
|
18
|
+
scope :by_project_id, lambda{|p_id| where(:project_id => p_id)}
|
19
|
+
scope :by_approving_user_id, lambda{|au_id| where(:approving_user_id => au_id)}
|
20
|
+
scope :by_targeted_user_id, lambda{|tu_id| where(:targeted_user_id => tu_id)}
|
21
|
+
|
22
|
+
scope :by_transaction_type_number, lambda{|tt_num| where( transaction: {transaction_type: {number: tt_num}})}
|
23
|
+
|
24
|
+
validates_presence_of :type, :amount_cents, :transaction, :account
|
25
|
+
|
26
|
+
composed_of :amount,
|
27
|
+
:class_name => "Money",
|
28
|
+
:mapping => [%w(amount_cents cents), %w(currency currency_as_string)],
|
29
|
+
:constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
|
30
|
+
:converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# The Asset class is an account type used to represents resources owned by the business entity.
|
3
|
+
#
|
4
|
+
# === Normal Balance
|
5
|
+
# The normal balance on Asset accounts is a *Debit*.
|
6
|
+
#
|
7
|
+
# @see http://en.wikipedia.org/wiki/Asset Assets
|
8
|
+
#
|
9
|
+
class Asset < Account
|
10
|
+
|
11
|
+
# The balance of the account.
|
12
|
+
#
|
13
|
+
# Assets have normal debit balances, so the credits are subtracted from the debits
|
14
|
+
# unless this is a contra account, in which debits are subtracted from credits
|
15
|
+
#
|
16
|
+
# @return [Money] The value balance
|
17
|
+
def balance(hash = {})
|
18
|
+
if contra
|
19
|
+
credits_balance(hash) - debits_balance(hash)
|
20
|
+
else
|
21
|
+
debits_balance(hash) - credits_balance(hash)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# The Equity class is an account type used to represents owners rights to the assets.
|
3
|
+
#
|
4
|
+
# === Normal Balance
|
5
|
+
# The normal balance on Equity accounts is a *Credit*.
|
6
|
+
#
|
7
|
+
# @see http://en.wikipedia.org/wiki/Equity_(finance) Equity
|
8
|
+
#
|
9
|
+
# @author Michael Bulat
|
10
|
+
class Equity < Account
|
11
|
+
|
12
|
+
# The balance of the account.
|
13
|
+
#
|
14
|
+
# Equity accounts have normal credit balances, so the debits are subtracted from the credits
|
15
|
+
# unless this is a contra account, in which credits are subtracted from debits
|
16
|
+
#
|
17
|
+
# @return [Money] The value balance
|
18
|
+
def balance(hash = {})
|
19
|
+
if contra
|
20
|
+
debits_balance(hash) - credits_balance(hash)
|
21
|
+
else
|
22
|
+
credits_balance(hash) - debits_balance(hash)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# The Expense class is an account type used to represents assets or services consumed in the generation of revenue.
|
3
|
+
#
|
4
|
+
# === Normal Balance
|
5
|
+
# The normal balance on Expense accounts is a *Debit*.
|
6
|
+
#
|
7
|
+
# @see http://en.wikipedia.org/wiki/Expense Expenses
|
8
|
+
#
|
9
|
+
# @author Michael Bulat
|
10
|
+
class Expense < Account
|
11
|
+
|
12
|
+
# The balance of the account.
|
13
|
+
#
|
14
|
+
# Expenses have normal debit balances, so the credits are subtracted from the debits
|
15
|
+
# unless this is a contra account, in which debits are subtracted from credits
|
16
|
+
#
|
17
|
+
# @return [Money] The value balance
|
18
|
+
def balance(hash = {})
|
19
|
+
if contra
|
20
|
+
credits_balance(hash) - debits_balance(hash)
|
21
|
+
else
|
22
|
+
debits_balance(hash) - credits_balance(hash)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# The Liability class is an account type used to represents debts owed to outsiders.
|
3
|
+
#
|
4
|
+
# === Normal Balance
|
5
|
+
# The normal balance on Liability accounts is a *Credit*.
|
6
|
+
#
|
7
|
+
# @see http://en.wikipedia.org/wiki/Liability_(financial_accounting) Liability
|
8
|
+
#
|
9
|
+
class Liability < Account
|
10
|
+
|
11
|
+
# The balance of the account.
|
12
|
+
#
|
13
|
+
# Liability accounts have normal credit balances, so the debits are subtracted from the credits
|
14
|
+
# unless this is a contra account, in which credits are subtracted from debits
|
15
|
+
#
|
16
|
+
# @return [Money] The value balance
|
17
|
+
def balance(hash = {})
|
18
|
+
if contra
|
19
|
+
debits_balance(hash) - credits_balance(hash)
|
20
|
+
else
|
21
|
+
credits_balance(hash) - debits_balance(hash)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# The Revenue class is an account type used to represents increases in owners equity.
|
3
|
+
#
|
4
|
+
# === Normal Balance
|
5
|
+
# The normal balance on Revenue accounts is a *Credit*.
|
6
|
+
#
|
7
|
+
# @see http://en.wikipedia.org/wiki/Revenue Revenue
|
8
|
+
#
|
9
|
+
# @author Michael Bulat
|
10
|
+
class Revenue < Account
|
11
|
+
|
12
|
+
# The balance of the account.
|
13
|
+
#
|
14
|
+
# Revenue accounts have normal credit balances, so the debits are subtracted from the credits
|
15
|
+
# unless this is a contra account, in which credits are subtracted from debits
|
16
|
+
#
|
17
|
+
# @return [Money] The value balance
|
18
|
+
def balance(hash = {})
|
19
|
+
if contra
|
20
|
+
debits_balance(hash) - credits_balance(hash)
|
21
|
+
else
|
22
|
+
credits_balance(hash) - debits_balance(hash)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module DoubleDouble
|
2
|
+
# Transactions are the recording of debits and credits to various accounts.
|
3
|
+
# This table can be thought of as a traditional accounting Journal.
|
4
|
+
#
|
5
|
+
# Posting to a Ledger can be considered to happen automatically, since
|
6
|
+
# Accounts have the reverse 'has_many' relationship to either it's credit or
|
7
|
+
# debit transactions
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# cash = DoubleDouble::Asset.find_by_name('Cash')
|
11
|
+
# accounts_receivable = DoubleDouble::Asset.find_by_name('Accounts Receivable')
|
12
|
+
#
|
13
|
+
# debit_amount = DoubleDouble::DebitAmount.new(:account => cash, :amount => 1000)
|
14
|
+
# credit_amount = DoubleDouble::CreditAmount.new(:account => accounts_receivable, :amount => 1000)
|
15
|
+
#
|
16
|
+
# transaction = DoubleDouble::Transaction.new(:description => "Receiving payment on an invoice")
|
17
|
+
# transaction.debit_amounts << debit_amount
|
18
|
+
# transaction.credit_amounts << credit_amount
|
19
|
+
# transaction.save
|
20
|
+
#
|
21
|
+
# @see http://en.wikipedia.org/wiki/Journal_entry Journal Entry
|
22
|
+
#
|
23
|
+
class Transaction < ActiveRecord::Base
|
24
|
+
self.table_name = 'double_double_transactions'
|
25
|
+
|
26
|
+
attr_accessible :description, :commercial_document
|
27
|
+
|
28
|
+
belongs_to :transaction_type
|
29
|
+
belongs_to :commercial_document, :polymorphic => true
|
30
|
+
|
31
|
+
has_many :credit_amounts
|
32
|
+
has_many :debit_amounts
|
33
|
+
has_many :credit_accounts, :through => :credit_amounts, :source => :account
|
34
|
+
has_many :debit_accounts, :through => :debit_amounts, :source => :account
|
35
|
+
|
36
|
+
validates_presence_of :description
|
37
|
+
validate :has_credit_amounts?
|
38
|
+
validate :has_debit_amounts?
|
39
|
+
validate :amounts_cancel?
|
40
|
+
|
41
|
+
scope :by_transaction_type_number, lambda{|tt_num| where(transaction_type: {number: tt_num})}
|
42
|
+
|
43
|
+
# Simple API for building a transaction and associated debit and credit amounts
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# transaction = DoubleDouble::Transaction.build(
|
47
|
+
# description: "Sold some widgets",
|
48
|
+
# debits: [
|
49
|
+
# {account: "Accounts Receivable", amount: 50}],
|
50
|
+
# credits: [
|
51
|
+
# {account: "Sales Revenue", amount: 45},
|
52
|
+
# {account: "Sales Tax Payable", amount: 5}])
|
53
|
+
#
|
54
|
+
# @return [DoubleDouble::Transaction] A Transaction with built credit and debit objects ready for saving
|
55
|
+
def self.build(hash)
|
56
|
+
transaction = Transaction.new(description: hash[:description], commercial_document: hash[:commercial_document])
|
57
|
+
hash[:debits].each do |debit|
|
58
|
+
a = Account.find_by_name(debit[:account])
|
59
|
+
transaction.debit_amounts << DebitAmount.new(account: a, amount: debit[:amount], transaction: transaction, project_id: debit[:project_id], approving_user_id: debit[:approving_user_id], targeted_user_id: debit[:targeted_user_id])
|
60
|
+
end
|
61
|
+
hash[:credits].each do |credit|
|
62
|
+
a = Account.find_by_name(credit[:account])
|
63
|
+
transaction.credit_amounts << CreditAmount.new(account: a, amount: credit[:amount], transaction: transaction, project_id: credit[:project_id], approving_user_id: credit[:approving_user_id], targeted_user_id: credit[:targeted_user_id])
|
64
|
+
end
|
65
|
+
transaction.transaction_type = hash[:transaction_type] if hash.has_key?(:transaction_type)
|
66
|
+
transaction
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
def has_credit_amounts?
|
71
|
+
errors[:base] << "Transaction must have at least one credit amount" if self.credit_amounts.blank?
|
72
|
+
end
|
73
|
+
|
74
|
+
def has_debit_amounts?
|
75
|
+
errors[:base] << "Transaction must have at least one debit amount" if self.debit_amounts.blank?
|
76
|
+
end
|
77
|
+
|
78
|
+
def amounts_cancel?
|
79
|
+
errors[:base] << "The credit and debit amounts are not equal" if difference_of_amounts != 0
|
80
|
+
end
|
81
|
+
|
82
|
+
def difference_of_amounts
|
83
|
+
credit_amount_total = credit_amounts.inject(Money.new(0)) {|sum, credit_amount| sum + credit_amount.amount}
|
84
|
+
debit_amount_total = debit_amounts.inject(Money.new(0)) {|sum, debit_amount| sum + debit_amount.amount}
|
85
|
+
credit_amount_total - debit_amount_total
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|