double_double 0.0.2 → 0.1.0

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/.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