double_double 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/crftr/double_double.png)](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
|