double_double 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -2,9 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
- - jruby-19mode
6
5
  - rbx-19mode
7
6
  - ruby-head
8
- env:
9
- - JRUBY_OPTS="--1.9"
10
7
  script: rake
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # double_double
2
2
  [![Build Status](https://travis-ci.org/crftr/double_double.png)](https://travis-ci.org/crftr/double_double)
3
+ [![Dependency Status](https://gemnasium.com/crftr/double_double.png)](https://gemnasium.com/crftr/double_double)
4
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/crftr/double_double)
3
5
 
4
6
  A double-entry accounting system. Likely to change heavily in the coming days.
5
7
 
@@ -13,7 +13,7 @@ module DoubleDouble
13
13
  # normal balance swapped. For example, to remove equity, a "Drawing" account may be created
14
14
  # as a contra equity account as follows:
15
15
  #
16
- # DoubleDouble::Equity.create(:name => "Drawing", contra => true)
16
+ # DoubleDouble::Equity.create(name: "Drawing", number: 2002, contra: true)
17
17
  #
18
18
  # At all times the balance of all accounts should conform to the "accounting equation"
19
19
  # DoubleDouble::Assets = Liabilties + Owner's Equity
@@ -35,18 +35,19 @@ module DoubleDouble
35
35
 
36
36
  has_many :credit_amounts
37
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
38
+ has_many :credit_transactions, through: :credit_amounts, source: :transaction
39
+ has_many :debit_transactions, through: :debit_amounts, source: :transaction
40
40
 
41
41
  validates_presence_of :type, :name, :number
42
42
  validates_uniqueness_of :name, :number
43
43
 
44
44
  def side_balance(is_debit, hash)
45
+ hash_keys = hash.keys
45
46
  a = is_debit ? DoubleDouble::DebitAmount.scoped : DoubleDouble::CreditAmount.scoped
46
47
  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)
48
+ a = a.by_context(hash[:context_id], hash[:context_type]) if (hash_keys & [:context_id, :context_type]).count == 2
49
+ a = a.by_initiator(hash[:initiator_id], hash[:initiator_type]) if (hash_keys & [:initiator_id, :initiator_type]).count == 2
50
+ a = a.by_accountee(hash[:accountee_id], hash[:accountee_type]) if (hash_keys & [:accountee_id, :accountee_type]).count == 2
50
51
  Money.new(a.sum(:amount_cents))
51
52
  end
52
53
 
@@ -80,6 +81,30 @@ module DoubleDouble
80
81
  end
81
82
  accounts_balance
82
83
  end
83
-
84
+
85
+ protected
86
+ # Left Side Accounts:
87
+ # if contra { credits_balance(hash) - debits_balance(hash) }
88
+ # else { debits_balance(hash) - credits_balance(hash) }
89
+ #
90
+ # Right Side Accounts:
91
+ # if contra { debits_balance(hash) - credits_balance(hash) }
92
+ # else { credits_balance(hash) - debits_balance(hash) }
93
+ #
94
+ # @return [Money] The balance of the account instance
95
+ def child_account_balance(is_left_side_account, hash = {})
96
+ if (is_left_side_account && contra) || !(is_left_side_account || contra)
97
+ credits_balance(hash) - debits_balance(hash)
98
+ else
99
+ debits_balance(hash) - credits_balance(hash)
100
+ end
101
+ end
84
102
  end
85
103
  end
104
+
105
+
106
+
107
+
108
+
109
+
110
+
@@ -7,27 +7,26 @@ module DoubleDouble
7
7
  class Amount < ActiveRecord::Base
8
8
  self.table_name = 'double_double_amounts'
9
9
 
10
- attr_accessible :account, :amount, :transaction, :project_id, :approving_user_id, :targeted_user_id
10
+ attr_accessible :account, :amount, :transaction, :context, :initiator, :accountee
11
11
 
12
12
  belongs_to :transaction
13
13
  belongs_to :account
14
- belongs_to :project
15
- belongs_to :approving_user, :class_name => "User"
16
- belongs_to :targeted_user, :class_name => "User"
14
+ belongs_to :context, polymorphic: true
15
+ belongs_to :initiator, polymorphic: true
16
+ belongs_to :accountee, polymorphic: true
17
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)}
18
+ scope :by_context, ->(c_id, c_base_class) { where(context_id: c_id, context_type: c_base_class) }
19
+ scope :by_initiator, ->(i_id, i_base_class) { where(initiator_id: i_id, initiator_type: i_base_class) }
20
+ scope :by_accountee, ->(a_id, a_base_class) { where(accountee_id: a_id, accountee_type: a_base_class) }
21
21
 
22
- scope :by_transaction_type_number, lambda{|tt_num| where( transaction: {transaction_type: {number: tt_num}})}
22
+ # scope :by_transaction_type_number, -> {|tt_num| where( transaction: {transaction_type: {number: tt_num}})}
23
23
 
24
24
  validates_presence_of :type, :amount_cents, :transaction, :account
25
25
 
26
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
-
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") }
32
31
  end
33
32
  end
@@ -6,20 +6,6 @@ module DoubleDouble
6
6
  #
7
7
  # @see http://en.wikipedia.org/wiki/Asset Assets
8
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
9
+ class Asset < LeftSideAccount
24
10
  end
25
11
  end
@@ -2,7 +2,7 @@ module DoubleDouble
2
2
  # The CreditAmount class represents credit entries in the transaction journal.
3
3
  #
4
4
  # @example
5
- # credit_amount = DoubleDouble::CreditAmount.new(:account => revenue, :amount => 1000)
5
+ # credit_amount = DoubleDouble::CreditAmount.new(account: "revenue", amount: 1000)
6
6
  #
7
7
  class CreditAmount < Amount
8
8
  end
@@ -2,7 +2,7 @@ module DoubleDouble
2
2
  # The DebitAmount class represents debit entries in the transaction journal.
3
3
  #
4
4
  # @example
5
- # debit_amount = DoubleDouble::DebitAmount.new(:account => cash, :amount => 1000)
5
+ # debit_amount = DoubleDouble::DebitAmount.new(account: "cash", amount: 1000)
6
6
  #
7
7
  class DebitAmount < Amount
8
8
  end
@@ -6,21 +6,6 @@ module DoubleDouble
6
6
  #
7
7
  # @see http://en.wikipedia.org/wiki/Equity_(finance) Equity
8
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
9
+ class Equity < RightSideAccount
25
10
  end
26
11
  end
@@ -6,21 +6,6 @@ module DoubleDouble
6
6
  #
7
7
  # @see http://en.wikipedia.org/wiki/Expense Expenses
8
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
9
+ class Expense < LeftSideAccount
25
10
  end
26
11
  end
@@ -0,0 +1,7 @@
1
+ module DoubleDouble
2
+ class LeftSideAccount < Account
3
+ def balance(hash = {})
4
+ child_account_balance(true, hash)
5
+ end
6
+ end
7
+ end
@@ -6,20 +6,6 @@ module DoubleDouble
6
6
  #
7
7
  # @see http://en.wikipedia.org/wiki/Liability_(financial_accounting) Liability
8
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
9
+ class Liability < RightSideAccount
24
10
  end
25
11
  end
@@ -6,21 +6,6 @@ module DoubleDouble
6
6
  #
7
7
  # @see http://en.wikipedia.org/wiki/Revenue Revenue
8
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
9
+ class Revenue < RightSideAccount
25
10
  end
26
11
  end
@@ -0,0 +1,7 @@
1
+ module DoubleDouble
2
+ class RightSideAccount < Account
3
+ def balance(hash = {})
4
+ child_account_balance(false, hash)
5
+ end
6
+ end
7
+ end
@@ -10,10 +10,10 @@ module DoubleDouble
10
10
  # cash = DoubleDouble::Asset.find_by_name('Cash')
11
11
  # accounts_receivable = DoubleDouble::Asset.find_by_name('Accounts Receivable')
12
12
  #
13
- # debit_amount = DoubleDouble::DebitAmount.new(:account => cash, :amount => 1000)
14
- # credit_amount = DoubleDouble::CreditAmount.new(:account => accounts_receivable, :amount => 1000)
13
+ # debit_amount = DoubleDouble::DebitAmount.new(account: 'cash', amount: 1000)
14
+ # credit_amount = DoubleDouble::CreditAmount.new(account: 'accounts_receivable', amount: 1000)
15
15
  #
16
- # transaction = DoubleDouble::Transaction.new(:description => "Receiving payment on an invoice")
16
+ # transaction = DoubleDouble::Transaction.new(description: "Receiving payment on an invoice")
17
17
  # transaction.debit_amounts << debit_amount
18
18
  # transaction.credit_amounts << credit_amount
19
19
  # transaction.save
@@ -23,22 +23,21 @@ module DoubleDouble
23
23
  class Transaction < ActiveRecord::Base
24
24
  self.table_name = 'double_double_transactions'
25
25
 
26
- attr_accessible :description, :commercial_document
26
+ attr_accessible :description
27
27
 
28
28
  belongs_to :transaction_type
29
- belongs_to :commercial_document, :polymorphic => true
30
29
 
31
30
  has_many :credit_amounts
32
31
  has_many :debit_amounts
33
32
  has_many :credit_accounts, :through => :credit_amounts, :source => :account
34
- has_many :debit_accounts, :through => :debit_amounts, :source => :account
33
+ has_many :debit_accounts, :through => :debit_amounts, :source => :account
35
34
 
36
35
  validates_presence_of :description
37
36
  validate :has_credit_amounts?
38
37
  validate :has_debit_amounts?
39
38
  validate :amounts_cancel?
40
39
 
41
- scope :by_transaction_type_number, lambda{|tt_num| where(transaction_type: {number: tt_num})}
40
+ scope :by_transaction_type_number, ->(tt_num) { where(transaction_type: {number: tt_num})}
42
41
 
43
42
  # Simple API for building a transaction and associated debit and credit amounts
44
43
  #
@@ -53,17 +52,17 @@ module DoubleDouble
53
52
  #
54
53
  # @return [DoubleDouble::Transaction] A Transaction with built credit and debit objects ready for saving
55
54
  def self.build(hash)
56
- transaction = Transaction.new(description: hash[:description], commercial_document: hash[:commercial_document])
55
+ t = Transaction.new(description: hash[:description])
57
56
  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])
57
+ new_debit_amount = prepare_amount_parameters debit.merge!({transaction: t})
58
+ t.debit_amounts << DebitAmount.new(new_debit_amount)
60
59
  end
61
60
  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])
61
+ new_credit_amount = prepare_amount_parameters credit.merge!({transaction: t})
62
+ t.credit_amounts << CreditAmount.new(new_credit_amount)
64
63
  end
65
- transaction.transaction_type = hash[:transaction_type] if hash.has_key?(:transaction_type)
66
- transaction
64
+ t.transaction_type = hash[:transaction_type] if hash.has_key?(:transaction_type)
65
+ t
67
66
  end
68
67
 
69
68
  private
@@ -81,8 +80,26 @@ module DoubleDouble
81
80
 
82
81
  def difference_of_amounts
83
82
  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}
83
+ debit_amount_total = debit_amounts.inject(Money.new(0)) {|sum, debit_amount| sum + debit_amount.amount}
85
84
  credit_amount_total - debit_amount_total
86
85
  end
86
+
87
+ def self.prepare_amount_parameters args
88
+ prepared_params = { account: Account.find_by_name(args[:account]), transaction: args[:transaction], amount: args[:amount]}
89
+
90
+ args_keys = args.keys
91
+ if (args_keys & [:context_id, :context_type]).count == 2
92
+ prepared_params.merge!({context_id: args[:context_id], context_type: args[:context_type]})
93
+ end
94
+
95
+ if (args_keys & [:initiator_id, :initiator_type]).count == 2
96
+ prepared_params.merge!({initiator_id: args[:initiator_id], initiator_type: args[:initiator_type]})
97
+ end
98
+
99
+ if (args_keys & [:accountee_id, :accountee_type]).count == 2
100
+ prepared_params.merge!({accountee_id: args[:accountee_id], accountee_type: args[:accountee_type]})
101
+ end
102
+ prepared_params
103
+ end
87
104
  end
88
105
  end
@@ -1,5 +1,4 @@
1
1
  module DoubleDouble
2
-
3
2
  class TransactionType < ActiveRecord::Base
4
3
  self.table_name = 'double_double_transaction_types'
5
4
 
@@ -9,5 +8,4 @@ module DoubleDouble
9
8
  validates_numericality_of :number, greater_than: 0
10
9
  validates_length_of :description, minimum: 6
11
10
  end
12
-
13
11
  end
@@ -1,3 +1,3 @@
1
1
  module DoubleDouble
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/double_double.rb CHANGED
@@ -5,6 +5,8 @@ require 'double_double/version'
5
5
 
6
6
  # Accounts
7
7
  require 'double_double/account'
8
+ require 'double_double/left_side_account'
9
+ require 'double_double/right_side_account'
8
10
  require 'double_double/asset'
9
11
  require 'double_double/equity'
10
12
  require 'double_double/expense'
@@ -1,20 +1,20 @@
1
1
  FactoryGirl.define do
2
- factory :account, :class => DoubleDouble::Account do |account|
2
+ factory :account, class: DoubleDouble::Account do |account|
3
3
  account.name { FactoryGirl.generate(:account_name) }
4
4
  account.number { FactoryGirl.generate(:account_number)}
5
5
  account.contra false
6
6
 
7
- factory :asset, :class => DoubleDouble::Asset
8
- factory :equity, :class => DoubleDouble::Equity
9
- factory :expense, :class => DoubleDouble::Expense
10
- factory :liability, :class => DoubleDouble::Liability
11
- factory :revenue, :class => DoubleDouble::Revenue
7
+ factory :asset, class: DoubleDouble::Asset
8
+ factory :equity, class: DoubleDouble::Equity
9
+ factory :expense, class: DoubleDouble::Expense
10
+ factory :liability, class: DoubleDouble::Liability
11
+ factory :revenue, class: DoubleDouble::Revenue
12
12
 
13
- factory :not_asset, :class => DoubleDouble::Liability
14
- factory :not_equity, :class => DoubleDouble::Asset
15
- factory :not_expense, :class => DoubleDouble::Liability
16
- factory :not_liability, :class => DoubleDouble::Asset
17
- factory :not_revenue, :class => DoubleDouble::Asset
13
+ factory :not_asset, class: DoubleDouble::Liability
14
+ factory :not_equity, class: DoubleDouble::Asset
15
+ factory :not_expense, class: DoubleDouble::Liability
16
+ factory :not_liability, class: DoubleDouble::Asset
17
+ factory :not_revenue, class: DoubleDouble::Asset
18
18
  end
19
19
 
20
20
  sequence :account_name do |n|
@@ -1,10 +1,10 @@
1
1
  FactoryGirl.define do
2
- factory :amount, :class => DoubleDouble::Amount do |amount|
2
+ factory :amount, class: DoubleDouble::Amount do |amount|
3
3
  end
4
4
 
5
- factory :credit_amt, :class => DoubleDouble::CreditAmount do
5
+ factory :credit_amt, class: DoubleDouble::CreditAmount do
6
6
  end
7
7
 
8
- factory :debit_amt, :class => DoubleDouble::DebitAmount do
8
+ factory :debit_amt, class: DoubleDouble::DebitAmount do
9
9
  end
10
10
  end
@@ -1,5 +1,5 @@
1
1
  FactoryGirl.define do
2
- factory :transaction, :class => DoubleDouble::Transaction do
2
+ factory :transaction, class: DoubleDouble::Transaction do
3
3
  description { FactoryGirl.generate(:transaction_type_description) }
4
4
  end
5
5
 
@@ -1,5 +1,5 @@
1
1
  FactoryGirl.define do
2
- factory :transaction_type, :class => DoubleDouble::TransactionType do |type|
2
+ factory :transaction_type, class: DoubleDouble::TransactionType do |type|
3
3
  type.description { FactoryGirl.generate(:transaction_type_description) }
4
4
  type.number { FactoryGirl.generate(:transaction_type_number) }
5
5
  end
@@ -19,28 +19,28 @@ module DoubleDouble
19
19
  credit_amount.should_not be_valid
20
20
  end
21
21
 
22
- it "should be sensitive to project_id when calculating balances, if supplied" do
22
+ it "should be sensitive to 'context' when calculating balances, if supplied" do
23
23
  acct_1 = FactoryGirl.create(:asset)
24
24
  other_acct = FactoryGirl.create(:not_asset)
25
25
  t = FactoryGirl.build(:transaction)
26
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(123), account: acct_1, project_id: 77)
26
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(123), account: acct_1, context_id: 77, context_type: 'Job')
27
27
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(123), account: other_acct)
28
28
  t.save
29
29
  t = FactoryGirl.build(:transaction)
30
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(321), account: acct_1, project_id: 77)
30
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(321), account: acct_1, context_id: 77, context_type: 'Job')
31
31
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(321), account: other_acct)
32
32
  t.save
33
33
  t = FactoryGirl.build(:transaction)
34
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(275), account: acct_1, project_id: 82)
34
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(275), account: acct_1, context_id: 82, context_type: 'Job')
35
35
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(275), account: other_acct)
36
36
  t.save
37
37
  t = FactoryGirl.build(:transaction)
38
38
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(999), account: acct_1)
39
39
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(999), account: other_acct)
40
40
  t.save
41
- acct_1.credits_balance({project_id: 77}).should == Money.new(123 + 321)
42
- acct_1.credits_balance({project_id: 82}).should == Money.new(275)
43
- acct_1.credits_balance.should == Money.new(123 + 321 + 275 + 999)
41
+ acct_1.credits_balance({context_id: 77, context_type: 'Job'}).should == Money.new(123 + 321)
42
+ acct_1.credits_balance({context_id: 82, context_type: 'Job'}).should == Money.new(275)
43
+ acct_1.credits_balance.should == Money.new(123 + 321 + 275 + 999)
44
44
  end
45
45
  end
46
46
  end
@@ -19,28 +19,28 @@ module DoubleDouble
19
19
  debit_amount.should_not be_valid
20
20
  end
21
21
 
22
- it "should be sensitive to project_id when calculating balances, if supplied" do
22
+ it "should be sensitive to context_id when calculating balances, if supplied" do
23
23
  acct_1 = FactoryGirl.create(:asset)
24
24
  other_acct = FactoryGirl.create(:not_asset)
25
25
  t = FactoryGirl.build(:transaction)
26
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(123), account: acct_1, project_id: 77)
26
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(123), account: acct_1, context_id: 77, context_type: 'Job')
27
27
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(123), account: other_acct)
28
28
  t.save
29
29
  t = FactoryGirl.build(:transaction)
30
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(321), account: acct_1, project_id: 77)
30
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(321), account: acct_1, context_id: 77, context_type: 'Job')
31
31
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(321), account: other_acct)
32
32
  t.save
33
33
  t = FactoryGirl.build(:transaction)
34
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(275), account: acct_1, project_id: 82)
34
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(275), account: acct_1, context_id: 82, context_type: 'Job')
35
35
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(275), account: other_acct)
36
36
  t.save
37
37
  t = FactoryGirl.build(:transaction)
38
38
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(999), account: acct_1)
39
39
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(999), account: other_acct)
40
40
  t.save
41
- acct_1.debits_balance({project_id: 77}).should == Money.new(123 + 321)
42
- acct_1.debits_balance({project_id: 82}).should == Money.new(275)
43
- acct_1.debits_balance.should == Money.new(123 + 321 + 275 + 999)
41
+ acct_1.debits_balance({context_id: 77, context_type: 'Job'}).should == Money.new(123 + 321)
42
+ acct_1.debits_balance({context_id: 82, context_type: 'Job'}).should == Money.new(275)
43
+ acct_1.debits_balance.should == Money.new(123 + 321 + 275 + 999)
44
44
  end
45
45
  end
46
46
  end
@@ -65,36 +65,21 @@ module DoubleDouble
65
65
  t.errors['base'].should == ["The credit and debit amounts are not equal"]
66
66
  end
67
67
 
68
- it "should have a polymorphic commercial document associations" do
69
- mock_document = FactoryGirl.create(:asset) # one would never do this, but it allows us to not require a migration for the test
70
-
71
- t = FactoryGirl.build(:transaction)
72
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(123), account: @acct)
73
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(123), account: @other_acct)
74
- t.commercial_document = mock_document
75
- t.save
76
-
77
- saved_transaction = Transaction.find(t.id)
78
- saved_transaction.commercial_document.should == mock_document
79
- end
80
-
81
68
  it "should allow building a transaction and credit and debits with a hash" do
82
69
  FactoryGirl.create(:asset, :name => "Accounts Receivable")
83
70
  FactoryGirl.create(:revenue, :name => "Sales Revenue")
84
71
  FactoryGirl.create(:liability, :name => "Sales Tax Payable")
85
- mock_document = FactoryGirl.create(:asset)
86
72
  transaction = Transaction.build(
87
73
  description: "Sold some widgets",
88
- commercial_document: mock_document,
89
74
  debits: [
90
75
  {account: "Accounts Receivable", amount: 50}],
91
76
  credits: [
92
77
  {account: "Sales Revenue", amount: 45},
93
78
  {account: "Sales Tax Payable", amount: 5}])
79
+
94
80
  transaction.should be_valid
95
81
  transaction.save
96
82
  saved_transaction = DoubleDouble::Transaction.find(transaction.id)
97
- saved_transaction.commercial_document.should == mock_document
98
83
  end
99
84
 
100
85
  end
data/spec/spec_helper.rb CHANGED
@@ -10,23 +10,18 @@ ActiveRecord::Migration.verbose = false
10
10
  @migration = Class.new(ActiveRecord::Migration) do
11
11
  def change
12
12
  create_table :double_double_accounts do |t|
13
- t.integer :number, null: false
14
- t.string :name
15
- t.string :type
16
- t.boolean :contra
17
-
18
- t.timestamps
13
+ t.integer :number, null: false
14
+ t.string :name, null: false
15
+ t.string :type, null: false
16
+ t.boolean :contra, default: false
19
17
  end
20
18
  add_index :double_double_accounts, [:name, :type]
21
19
 
22
20
  create_table :double_double_transactions do |t|
23
21
  t.string :description
24
- t.integer :commercial_document_id
25
- t.string :commercial_document_type
26
22
  t.references :transaction_type
27
23
  t.timestamps
28
24
  end
29
- add_index :double_double_transactions, [:commercial_document_id, :commercial_document_type], :name => "index_transactions_on_commercial_doc"
30
25
  add_index :double_double_transactions, :transaction_type_id
31
26
 
32
27
  create_table :double_double_transaction_types do |t|
@@ -39,15 +34,19 @@ ActiveRecord::Migration.verbose = false
39
34
  t.string :type
40
35
  t.references :account
41
36
  t.references :transaction
42
- t.references :project
43
- t.references :approving_user
44
- t.references :targeted_user
45
- t.integer :amount_cents, :limit => 8, :default => 0, :null => false
37
+ t.references :context, polymorphic: true
38
+ t.references :initiator, polymorphic: true
39
+ t.references :accountee, polymorphic: true
40
+
41
+ t.integer :amount_cents, limit: 8, default: 0, null: false
46
42
  t.string :currency
47
- end
48
- add_index :double_double_amounts, :project_id
49
- add_index :double_double_amounts, :approving_user_id
50
- add_index :double_double_amounts, :targeted_user_id
43
+ end
44
+ add_index :double_double_amounts, :context_id
45
+ add_index :double_double_amounts, :context_type
46
+ add_index :double_double_amounts, :initiator_id
47
+ add_index :double_double_amounts, :initiator_type
48
+ add_index :double_double_amounts, :accountee_id
49
+ add_index :double_double_amounts, :accountee_type
51
50
  add_index :double_double_amounts, :type
52
51
  add_index :double_double_amounts, [:account_id, :transaction_id]
53
52
  add_index :double_double_amounts, [:transaction_id, :account_id]
@@ -59,19 +59,19 @@ shared_examples "a left side account type" do
59
59
  a2 = rand(1_000_000_000)
60
60
  a3 = rand(1_000_000_000)
61
61
  a4 = rand(1_000_000_000)
62
- pid1 = 100
63
- pid2 = 200
62
+ context_id_1 = 100
63
+ context_id_2 = 200
64
64
 
65
65
  t = FactoryGirl.build(:transaction)
66
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a1), account: acct1, project_id: pid1)
66
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a1), account: acct1, context_id: context_id_1, context_type: 'Job')
67
67
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a1), account: other_account)
68
68
  t.save
69
69
  t = FactoryGirl.build(:transaction)
70
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: acct1, project_id: pid1)
70
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: acct1, context_id: context_id_1, context_type: 'Job')
71
71
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: other_account)
72
72
  t.save
73
73
  t = FactoryGirl.build(:transaction)
74
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: acct1, project_id: pid2)
74
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: acct1, context_id: context_id_2, context_type: 'Job')
75
75
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: other_account)
76
76
  t.save
77
77
  t = FactoryGirl.build(:transaction)
@@ -81,15 +81,15 @@ shared_examples "a left side account type" do
81
81
 
82
82
  t = FactoryGirl.build(:transaction)
83
83
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a4), account: other_account)
84
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct1, project_id: pid1)
84
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct1, context_id: context_id_1, context_type: 'Job')
85
85
  t.save
86
86
  t = FactoryGirl.build(:transaction)
87
87
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: other_account)
88
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct1, project_id: pid1)
88
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct1, context_id: context_id_1, context_type: 'Job')
89
89
  t.save
90
90
  t = FactoryGirl.build(:transaction)
91
91
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
92
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct1, project_id: pid2)
92
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct1, context_id: context_id_2, context_type: 'Job')
93
93
  t.save
94
94
  t = FactoryGirl.build(:transaction)
95
95
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
@@ -98,27 +98,27 @@ shared_examples "a left side account type" do
98
98
 
99
99
  t = FactoryGirl.build(:transaction)
100
100
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a4), account: other_account)
101
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct2, project_id: pid1)
101
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct2, context_id: context_id_1, context_type: 'Job')
102
102
  t.save
103
103
  t = FactoryGirl.build(:transaction)
104
104
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: other_account)
105
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct2, project_id: pid1)
105
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct2, context_id: context_id_1, context_type: 'Job')
106
106
  t.save
107
107
  t = FactoryGirl.build(:transaction)
108
108
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
109
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct2, project_id: pid2)
109
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct2, context_id: context_id_2, context_type: 'Job')
110
110
  t.save
111
111
  t = FactoryGirl.build(:transaction)
112
112
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
113
113
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct2)
114
114
  t.save
115
115
 
116
- acct1.balance({project_id: pid1}).should == Money.new((a4 + a2) - (a1 + a2))
117
- acct1.balance({project_id: pid2}).should == Money.new(a3 - a3)
116
+ acct1.balance({context_id: context_id_1, context_type: 'Job'}).should == Money.new((a4 + a2) - (a1 + a2))
117
+ acct1.balance({context_id: context_id_2, context_type: 'Job'}).should == Money.new(a3 - a3)
118
118
  acct1.balance.should == Money.new((a4 + a2 + a3 + a3) - (a1 + a2 + a3 + a3))
119
119
 
120
- acct2.balance({project_id: pid1}).should == Money.new((a4 + a2))
121
- acct2.balance({project_id: pid2}).should == Money.new(a3)
120
+ acct2.balance({context_id: context_id_1, context_type: 'Job'}).should == Money.new((a4 + a2))
121
+ acct2.balance({context_id: context_id_2, context_type: 'Job'}).should == Money.new(a3)
122
122
  acct2.balance.should == Money.new((a4 + a2 + a3 + a3))
123
123
  end
124
124
  end
@@ -59,19 +59,19 @@ shared_examples "a right side account type" do
59
59
  a2 = rand(1_000_000_000)
60
60
  a3 = rand(1_000_000_000)
61
61
  a4 = rand(1_000_000_000)
62
- pid1 = 100
63
- pid2 = 200
62
+ context_id_1 = 100
63
+ context_id_2 = 200
64
64
 
65
65
  t = FactoryGirl.build(:transaction)
66
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a1), account: acct1, project_id: pid1)
66
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a1), account: acct1, context_id: context_id_1, context_type: 'Job')
67
67
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a1), account: other_account)
68
68
  t.save
69
69
  t = FactoryGirl.build(:transaction)
70
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: acct1, project_id: pid1)
70
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: acct1, context_id: context_id_1, context_type: 'Job')
71
71
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: other_account)
72
72
  t.save
73
73
  t = FactoryGirl.build(:transaction)
74
- t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: acct1, project_id: pid2)
74
+ t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: acct1, context_id: context_id_2, context_type: 'Job')
75
75
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: other_account)
76
76
  t.save
77
77
  t = FactoryGirl.build(:transaction)
@@ -81,15 +81,15 @@ shared_examples "a right side account type" do
81
81
 
82
82
  t = FactoryGirl.build(:transaction)
83
83
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a4), account: other_account)
84
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct1, project_id: pid1)
84
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct1, context_id: context_id_1, context_type: 'Job')
85
85
  t.save
86
86
  t = FactoryGirl.build(:transaction)
87
87
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: other_account)
88
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct1, project_id: pid1)
88
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct1, context_id: context_id_1, context_type: 'Job')
89
89
  t.save
90
90
  t = FactoryGirl.build(:transaction)
91
91
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
92
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct1, project_id: pid2)
92
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct1, context_id: context_id_2, context_type: 'Job')
93
93
  t.save
94
94
  t = FactoryGirl.build(:transaction)
95
95
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
@@ -98,27 +98,27 @@ shared_examples "a right side account type" do
98
98
 
99
99
  t = FactoryGirl.build(:transaction)
100
100
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a4), account: other_account)
101
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct2, project_id: pid1)
101
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a4), account: acct2, context_id: context_id_1, context_type: 'Job')
102
102
  t.save
103
103
  t = FactoryGirl.build(:transaction)
104
104
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a2), account: other_account)
105
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct2, project_id: pid1)
105
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a2), account: acct2, context_id: context_id_1, context_type: 'Job')
106
106
  t.save
107
107
  t = FactoryGirl.build(:transaction)
108
108
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
109
- t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct2, project_id: pid2)
109
+ t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct2, context_id: context_id_2, context_type: 'Job')
110
110
  t.save
111
111
  t = FactoryGirl.build(:transaction)
112
112
  t.credit_amounts << FactoryGirl.create(:credit_amt, transaction: t, amount: Money.new(a3), account: other_account)
113
113
  t.debit_amounts << FactoryGirl.create(:debit_amt, transaction: t, amount: Money.new(a3), account: acct2)
114
114
  t.save
115
115
 
116
- acct1.balance({project_id: pid1}).should == Money.new((a1 + a2) - (a4 + a2))
117
- acct1.balance({project_id: pid2}).should == Money.new(a3 - a3)
116
+ acct1.balance({context_id: context_id_1, context_type: 'Job'}).should == Money.new((a1 + a2) - (a4 + a2))
117
+ acct1.balance({context_id: context_id_2, context_type: 'Job'}).should == Money.new(a3 - a3)
118
118
  acct1.balance.should == Money.new((a1 + a2 + a3 + a3) - (a4 + a2 + a3 + a3))
119
119
 
120
- acct2.balance({project_id: pid1}).should == Money.new(- (a4 + a2))
121
- acct2.balance({project_id: pid2}).should == Money.new(- a3)
120
+ acct2.balance({context_id: context_id_1, context_type: 'Job'}).should == Money.new(- (a4 + a2))
121
+ acct2.balance({context_id: context_id_2, context_type: 'Job'}).should == Money.new(- a3)
122
122
  acct2.balance.should == Money.new(- (a4 + a2 + a3 + a3))
123
123
  end
124
124
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: double_double
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-26 00:00:00.000000000 Z
12
+ date: 2013-01-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: money
@@ -146,8 +146,10 @@ files:
146
146
  - lib/double_double/debit_amount.rb
147
147
  - lib/double_double/equity.rb
148
148
  - lib/double_double/expense.rb
149
+ - lib/double_double/left_side_account.rb
149
150
  - lib/double_double/liability.rb
150
151
  - lib/double_double/revenue.rb
152
+ - lib/double_double/right_side_account.rb
151
153
  - lib/double_double/transaction.rb
152
154
  - lib/double_double/transaction_type.rb
153
155
  - lib/double_double/version.rb