double_entry 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e815a7e5aabf260a4697a11f7685d362c017cdfb
4
- data.tar.gz: 416041a85f823156b3211c58edcb751a07ea60d1
3
+ metadata.gz: bee621c780c82e734a95964749650675683f1460
4
+ data.tar.gz: 326d9d02768905beede8b785215b1eb164a4c8cc
5
5
  SHA512:
6
- metadata.gz: 0b36f7c934a87f36ec0250d360b043e4a98c033bd74289eaa9cade1e120f35fa438376629bb8d099de122481f28411ecc4a6890641646e56ba49afad52d99312
7
- data.tar.gz: 4c8a843ba84218611d2545b161f58cddbb03617c94564027f02e85957e6754d299d5381f37527e5cc0f7b3e58e05a4821fb27c82883b750fe139db61e901cf0c
6
+ metadata.gz: e98f6f1a3b11a5bd9f8b4e384eb3dff8a6cd56b40ae3f8b430565fdbc601e3532a6cc95f8fdacc469457425533745d99a7b6cc8accaf4a6dd67b0d2b27ed41b0
7
+ data.tar.gz: 945ba3173e2b170e1cee74fcb89e31f8ce4a2245fa75dbe6efa267850196c7470495ffd3b4f47bae23acef6aa89722e7ca0379a53ff927ca7f8e49d9727fdb48
@@ -3,13 +3,23 @@ module DoubleEntry
3
3
  class Account
4
4
 
5
5
  class << self
6
- attr_writer :accounts
6
+ attr_writer :accounts, :scope_identifier_max_length, :account_identifier_max_length
7
7
 
8
8
  # @api private
9
9
  def accounts
10
10
  @accounts ||= Set.new
11
11
  end
12
12
 
13
+ # @api private
14
+ def scope_identifier_max_length
15
+ @scope_identifier_max_length ||= 23
16
+ end
17
+
18
+ # @api private
19
+ def account_identifier_max_length
20
+ @account_identifier_max_length ||= 31
21
+ end
22
+
13
23
  # @api private
14
24
  def account(identifier, options = {})
15
25
  account = accounts.find(identifier, options[:scope].present?)
@@ -128,7 +138,12 @@ module DoubleEntry
128
138
  private
129
139
 
130
140
  def ensure_scope_is_valid
131
- scope_identity
141
+ identity = scope_identity
142
+ if identity && identity.length > Account.scope_identifier_max_length
143
+ raise ScopeIdentifierTooLongError.new(
144
+ "scope identifier '#{identity}' is too long. Please limit it to #{Account.scope_identifier_max_length} characters."
145
+ )
146
+ end
132
147
  end
133
148
  end
134
149
 
@@ -139,6 +154,11 @@ module DoubleEntry
139
154
  @scope_identifier = args[:scope_identifier]
140
155
  @positive_only = args[:positive_only]
141
156
  @currency = args[:currency] || Money.default_currency
157
+ if identifier.length > Account.account_identifier_max_length
158
+ raise AccountIdentifierTooLongError.new(
159
+ "account identifier '#{identifier}' is too long. Please limit it to #{Account.account_identifier_max_length} characters."
160
+ )
161
+ end
142
162
  end
143
163
 
144
164
  def scoped?
@@ -3,8 +3,24 @@ module DoubleEntry
3
3
  include Configurable
4
4
 
5
5
  class Configuration
6
- delegate :accounts, :accounts=, :to => "DoubleEntry::Account"
7
- delegate :transfers, :transfers=, :to => "DoubleEntry::Transfer"
6
+
7
+ delegate(
8
+ :accounts,
9
+ :accounts=,
10
+ :scope_identifier_max_length,
11
+ :scope_identifier_max_length=,
12
+ :account_identifier_max_length,
13
+ :account_identifier_max_length=,
14
+ :to => "DoubleEntry::Account",
15
+ )
16
+
17
+ delegate(
18
+ :transfers,
19
+ :transfers=,
20
+ :code_max_length,
21
+ :code_max_length=,
22
+ :to => "DoubleEntry::Transfer",
23
+ )
8
24
 
9
25
  def define_accounts
10
26
  yield accounts
@@ -1,8 +1,11 @@
1
1
  # encoding: utf-8
2
2
  module DoubleEntry
3
3
  class UnknownAccount < RuntimeError; end
4
+ class AccountIdentifierTooLongError < RuntimeError; end
5
+ class ScopeIdentifierTooLongError < RuntimeError; end
4
6
  class TransferNotAllowed < RuntimeError; end
5
7
  class TransferIsNegative < RuntimeError; end
8
+ class TransferCodeTooLongError < RuntimeError; end
6
9
  class DuplicateAccount < RuntimeError; end
7
10
  class DuplicateTransfer < RuntimeError; end
8
11
  class AccountWouldBeSentNegative < RuntimeError; end
@@ -2,7 +2,7 @@
2
2
  module DoubleEntry
3
3
  module Reporting
4
4
  class Aggregate
5
- attr_reader :function, :account, :code, :range, :options, :filter
5
+ attr_reader :function, :account, :code, :range, :options, :filter, :currency
6
6
 
7
7
  def initialize(function, account, code, options)
8
8
  @function = function.to_s
@@ -13,6 +13,7 @@ module DoubleEntry
13
13
  @options = options
14
14
  @range = options[:range]
15
15
  @filter = options[:filter]
16
+ @currency = DoubleEntry::Account.currency(account)
16
17
  end
17
18
 
18
19
  def amount(force_recalculation = false)
@@ -24,18 +25,12 @@ module DoubleEntry
24
25
  end
25
26
  end
26
27
 
27
- def formatted_amount
28
- Aggregate.formatted_amount(function, amount, currency)
29
- end
30
-
31
- def self.formatted_amount(function, amount, currency)
32
- safe_amount = amount || 0
33
-
34
- case function.to_s
35
- when 'count'
36
- safe_amount
28
+ def formatted_amount(amount = amount)
29
+ amount ||= 0
30
+ if function == "count"
31
+ amount
37
32
  else
38
- Money.new(safe_amount, currency)
33
+ Money.new(amount, currency)
39
34
  end
40
35
  end
41
36
 
@@ -46,10 +41,6 @@ module DoubleEntry
46
41
  aggregate.amount if aggregate
47
42
  end
48
43
 
49
- def currency
50
- DoubleEntry::Account.currency(account)
51
- end
52
-
53
44
  def clear_old_aggregates
54
45
  LineAggregate.delete_all(field_hash)
55
46
  end
@@ -75,28 +66,26 @@ module DoubleEntry
75
66
  # otherwise they will get excruciatingly slow to calculate
76
67
  # as the year progresses. (I am thinking mainly of the 'current' year.)
77
68
  # Combining monthly aggregates will mean that the figure will be partially memoized
78
- case function.to_s
79
- when 'average'
69
+ if function == "average"
80
70
  calculate_yearly_average
81
71
  else
82
- zero = Aggregate.formatted_amount(function, 0, currency)
83
-
72
+ zero = formatted_amount(0)
84
73
  result = (1..12).inject(zero) do |total, month|
85
- total += Reporting.aggregate(function, account, code,
86
- :range => MonthRange.new(:year => range.year, :month => month), :filter => filter)
74
+ total += Reporting.aggregate(
75
+ function, account, code,
76
+ :range => MonthRange.new(:year => range.year, :month => month),
77
+ :filter => filter,
78
+ )
87
79
  end
88
-
89
- result = result.cents if result.class == Money
90
- result
80
+ result.is_a?(Money) ? result.cents : result
91
81
  end
92
82
  end
93
83
 
94
84
  def calculate_yearly_average
95
85
  # need this seperate function, because an average of averages is not the correct average
96
- sum = Reporting.aggregate(:sum, account, code,
97
- :range => YearRange.new(:year => range.year), :filter => filter)
98
- count = Reporting.aggregate(:count, account, code,
99
- :range => YearRange.new(:year => range.year), :filter => filter)
86
+ year_range = YearRange.new(:year => range.year)
87
+ sum = Reporting.aggregate(:sum, account, code, :range => year_range, :filter => filter)
88
+ count = Reporting.aggregate(:count, account, code, :range => year_range, :filter => filter)
100
89
  (count == 0) ? 0 : (sum / count).cents
101
90
  end
102
91
 
@@ -9,16 +9,17 @@ module DoubleEntry
9
9
  #
10
10
  # For example, you could request all sales
11
11
  # broken down by month and it would return an array of values
12
- attr_reader :function, :account, :code, :filter, :range_type, :start, :finish
12
+ attr_reader :function, :account, :code, :filter, :range_type, :start, :finish, :currency
13
13
 
14
14
  def initialize(function, account, code, options)
15
- @function = function
15
+ @function = function.to_s
16
16
  @account = account
17
17
  @code = code
18
18
  @filter = options[:filter]
19
19
  @range_type = options[:range_type]
20
20
  @start = options[:start]
21
21
  @finish = options[:finish]
22
+ @currency = DoubleEntry::Account.currency(account)
22
23
 
23
24
  retrieve_aggregates
24
25
  fill_in_missing_aggregates
@@ -47,15 +48,14 @@ module DoubleEntry
47
48
  def retrieve_aggregates
48
49
  raise ArgumentError.new("Invalid range type '#{range_type}'") unless %w(year month week day hour).include? range_type
49
50
  @aggregates = LineAggregate.
50
- where(:function => function.to_s).
51
+ where(:function => function).
51
52
  where(:range_type => 'normal').
52
53
  where(:account => account.to_s).
53
54
  where(:code => code.to_s).
54
55
  where(:filter => filter.inspect).
55
56
  where(LineAggregate.arel_table[range_type].not_eq(nil)).
56
- inject({}) do |hash, result|
57
- hash[result.key] = Aggregate.formatted_amount(function, result.amount, currency)
58
- hash
57
+ each_with_object({}) do |hash, result|
58
+ hash[result.key] = formatted_amount(result.amount)
59
59
  end
60
60
  end
61
61
 
@@ -63,8 +63,13 @@ module DoubleEntry
63
63
  TimeRangeArray.make(range_type, start, finish)
64
64
  end
65
65
 
66
- def currency
67
- DoubleEntry::Account.currency(account)
66
+ def formatted_amount(amount)
67
+ amount ||= 0
68
+ if function == "count"
69
+ amount
70
+ else
71
+ Money.new(amount, currency)
72
+ end
68
73
  end
69
74
  end
70
75
  end
@@ -3,13 +3,18 @@ module DoubleEntry
3
3
  class Transfer
4
4
 
5
5
  class << self
6
- attr_writer :transfers
6
+ attr_writer :transfers, :code_max_length
7
7
 
8
8
  # @api private
9
9
  def transfers
10
10
  @transfers ||= Set.new
11
11
  end
12
12
 
13
+ # @api private
14
+ def code_max_length
15
+ @code_max_length ||= 47
16
+ end
17
+
13
18
  # @api private
14
19
  def transfer(amount, options = {})
15
20
  raise TransferIsNegative if amount < Money.zero
@@ -54,10 +59,17 @@ module DoubleEntry
54
59
  end
55
60
  end
56
61
 
57
- attr_accessor :code, :from, :to, :description
62
+ attr_reader :code, :from, :to
58
63
 
59
64
  def initialize(attributes)
60
- attributes.each { |name, value| send("#{name}=", value) }
65
+ @code = attributes[:code]
66
+ @from = attributes[:from]
67
+ @to = attributes[:to]
68
+ if code.length > Transfer.code_max_length
69
+ raise TransferCodeTooLongError.new(
70
+ "transfer code '#{code}' is too long. Please limit it to #{Transfer.code_max_length} characters."
71
+ )
72
+ end
61
73
  end
62
74
 
63
75
  def process(amount, from, to, code, detail)
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module DoubleEntry
4
- VERSION = "0.8.0"
4
+ VERSION = "0.9.0"
5
5
  end
@@ -2,56 +2,56 @@ class CreateDoubleEntryTables < ActiveRecord::Migration
2
2
 
3
3
  def self.up
4
4
  create_table "double_entry_account_balances", :force => true do |t|
5
- t.string "account", :null => false
6
- t.string "scope"
7
- t.integer "balance"
5
+ t.string "account", :limit => 31, :null => false
6
+ t.string "scope", :limit => 23
7
+ t.integer "balance", :null => false
8
8
  t.timestamps
9
9
  end
10
10
 
11
- add_index "double_entry_account_balances", ["account"], :name => "index_account_balances_on_account"
11
+ add_index "double_entry_account_balances", ["account"], :name => "index_account_balances_on_account"
12
12
  add_index "double_entry_account_balances", ["scope", "account"], :name => "index_account_balances_on_scope_and_account", :unique => true
13
13
 
14
14
  create_table "double_entry_lines", :force => true do |t|
15
- t.string "account"
16
- t.string "scope"
17
- t.string "code"
18
- t.integer "amount"
19
- t.integer "balance"
20
- t.integer "partner_id"
21
- t.string "partner_account"
22
- t.string "partner_scope"
23
- t.integer "detail_id"
24
- t.string "detail_type"
15
+ t.string "account", :limit => 31, :null => false
16
+ t.string "scope", :limit => 23
17
+ t.string "code", :limit => 47, :null => false
18
+ t.integer "amount", :null => false
19
+ t.integer "balance", :null => false
20
+ t.integer "partner_id"
21
+ t.string "partner_account", :limit => 31, :null => false
22
+ t.string "partner_scope", :limit => 23
23
+ t.integer "detail_id"
24
+ t.string "detail_type"
25
25
  t.timestamps
26
26
  end
27
27
 
28
- add_index "double_entry_lines", ["account", "code", "created_at"], :name => "lines_account_code_created_at_idx"
29
- add_index "double_entry_lines", ["account", "created_at"], :name => "lines_account_created_at_idx"
28
+ add_index "double_entry_lines", ["account", "code", "created_at"], :name => "lines_account_code_created_at_idx"
29
+ add_index "double_entry_lines", ["account", "created_at"], :name => "lines_account_created_at_idx"
30
30
  add_index "double_entry_lines", ["scope", "account", "created_at"], :name => "lines_scope_account_created_at_idx"
31
- add_index "double_entry_lines", ["scope", "account", "id"], :name => "lines_scope_account_id_idx"
31
+ add_index "double_entry_lines", ["scope", "account", "id"], :name => "lines_scope_account_id_idx"
32
32
 
33
33
  create_table "double_entry_line_aggregates", :force => true do |t|
34
- t.string "function"
35
- t.string "account"
36
- t.string "code"
37
- t.string "scope"
38
- t.integer "year"
39
- t.integer "month"
40
- t.integer "week"
41
- t.integer "day"
42
- t.integer "hour"
43
- t.integer "amount"
44
- t.string "filter"
45
- t.string "range_type"
34
+ t.string "function", :limit => 15, :null => false
35
+ t.string "account", :limit => 31, :null => false
36
+ t.string "code", :limit => 47
37
+ t.string "scope", :limit => 23
38
+ t.integer "year"
39
+ t.integer "month"
40
+ t.integer "week"
41
+ t.integer "day"
42
+ t.integer "hour"
43
+ t.integer "amount", :null => false
44
+ t.string "filter"
45
+ t.string "range_type", :limit => 15, :null => false
46
46
  t.timestamps
47
47
  end
48
48
 
49
49
  add_index "double_entry_line_aggregates", ["function", "account", "code", "year", "month", "week", "day"], :name => "line_aggregate_idx"
50
50
 
51
51
  create_table "double_entry_line_checks", :force => true do |t|
52
- t.integer "last_line_id"
53
- t.boolean "errors_found"
54
- t.text "log"
52
+ t.integer "last_line_id", :null => false
53
+ t.boolean "errors_found", :null => false
54
+ t.text "log"
55
55
  t.timestamps
56
56
  end
57
57
 
@@ -4,21 +4,54 @@ module DoubleEntry
4
4
  describe Account do
5
5
  let(:identity_scope) { ->(value) { value } }
6
6
 
7
- it "instances should be sortable" do
8
- account = Account.new(:identifier => "savings", :scope_identifier => identity_scope)
9
- a = Account::Instance.new(:account => account, :scope => "123")
10
- b = Account::Instance.new(:account => account, :scope => "456")
11
- expect([b, a].sort).to eq [a, b]
7
+ describe "::new" do
8
+ context "given an identifier 31 characters in length" do
9
+ let(:identifier) { "xxxxxxxx 31 characters xxxxxxxx" }
10
+ specify do
11
+ expect { Account.new(:identifier => identifier) }.to_not raise_error
12
+ end
13
+ end
14
+
15
+ context "given an identifier 32 characters in length" do
16
+ let(:identifier) { "xxxxxxxx 32 characters xxxxxxxxx" }
17
+ specify do
18
+ expect { Account.new(:identifier => identifier) }.to raise_error AccountIdentifierTooLongError, /'#{identifier}'/
19
+ end
20
+ end
12
21
  end
13
22
 
14
- it "instances should be hashable" do
15
- account = Account.new(:identifier => "savings", :scope_identifier => identity_scope)
16
- a1 = Account::Instance.new(:account => account, :scope => "123")
17
- a2 = Account::Instance.new(:account => account, :scope => "123")
18
- b = Account::Instance.new(:account => account, :scope => "456")
23
+ describe Account::Instance do
24
+ it "is sortable" do
25
+ account = Account.new(:identifier => "savings", :scope_identifier => identity_scope)
26
+ a = Account::Instance.new(:account => account, :scope => "123")
27
+ b = Account::Instance.new(:account => account, :scope => "456")
28
+ expect([b, a].sort).to eq [a, b]
29
+ end
30
+
31
+ it "is hashable" do
32
+ account = Account.new(:identifier => "savings", :scope_identifier => identity_scope)
33
+ a1 = Account::Instance.new(:account => account, :scope => "123")
34
+ a2 = Account::Instance.new(:account => account, :scope => "123")
35
+ b = Account::Instance.new(:account => account, :scope => "456")
36
+
37
+ expect(a1.hash).to eq a2.hash
38
+ expect(a1.hash).to_not eq b.hash
39
+ end
40
+
41
+ describe "::new" do
42
+ let(:account) { Account.new(:identifier => "x", :scope_identifier => identity_scope) }
43
+ subject(:initialize_account_instance) { Account::Instance.new(:account => account, :scope => scope) }
44
+
45
+ context "given a scope identifier 23 characters in length" do
46
+ let(:scope) { "xxxx 23 characters xxxx" }
47
+ specify { expect { initialize_account_instance }.to_not raise_error }
48
+ end
19
49
 
20
- expect(a1.hash).to eq a2.hash
21
- expect(a1.hash).to_not eq b.hash
50
+ context "given a scope identifier 24 characters in length" do
51
+ let(:scope) { "xxxx 24 characters xxxxx" }
52
+ specify { expect { initialize_account_instance }.to raise_error ScopeIdentifierTooLongError, /'#{scope}'/ }
53
+ end
54
+ end
22
55
  end
23
56
 
24
57
  describe "currency" do
@@ -32,27 +65,27 @@ module DoubleEntry
32
65
  expect(DoubleEntry::Account::Instance.new(:account => account).currency).to eq("AUD")
33
66
  end
34
67
  end
35
- end
36
68
 
37
- describe Account::Set do
38
- describe "#define" do
39
- context "given a 'savings' account is defined" do
40
- before { subject.define(:identifier => "savings") }
41
- its(:first) { should be_a Account }
42
- its("first.identifier") { should eq "savings" }
69
+ describe Account::Set do
70
+ describe "#define" do
71
+ context "given a 'savings' account is defined" do
72
+ before { subject.define(:identifier => "savings") }
73
+ its(:first) { should be_an Account }
74
+ its("first.identifier") { should eq "savings" }
75
+ end
43
76
  end
44
- end
45
77
 
46
- describe "#active_record_scope_identifier" do
47
- subject(:scope) { Account::Set.new.active_record_scope_identifier(ar_class) }
78
+ describe "#active_record_scope_identifier" do
79
+ subject(:scope) { Account::Set.new.active_record_scope_identifier(ar_class) }
48
80
 
49
- context "given ActiveRecordScopeFactory is stubbed" do
50
- let(:scope_identifier) { double(:scope_identifier) }
51
- let(:scope_factory) { double(:scope_factory, :scope_identifier => scope_identifier) }
52
- let(:ar_class) { double(:ar_class) }
53
- before { allow(Account::ActiveRecordScopeFactory).to receive(:new).with(ar_class).and_return(scope_factory) }
81
+ context "given ActiveRecordScopeFactory is stubbed" do
82
+ let(:scope_identifier) { double(:scope_identifier) }
83
+ let(:scope_factory) { double(:scope_factory, :scope_identifier => scope_identifier) }
84
+ let(:ar_class) { double(:ar_class) }
85
+ before { allow(Account::ActiveRecordScopeFactory).to receive(:new).with(ar_class).and_return(scope_factory) }
54
86
 
55
- it { should eq scope_identifier }
87
+ it { should eq scope_identifier }
88
+ end
56
89
  end
57
90
  end
58
91
  end
@@ -5,6 +5,35 @@ describe DoubleEntry::Configuration do
5
5
  its(:accounts) { should be_a DoubleEntry::Account::Set }
6
6
  its(:transfers) { should be_a DoubleEntry::Transfer::Set }
7
7
 
8
+ describe "max lengths" do
9
+ context "given a max length has not been set" do
10
+ its(:code_max_length) { should be 47 }
11
+ its(:scope_identifier_max_length) { should be 23 }
12
+ its(:account_identifier_max_length) { should be 31 }
13
+ end
14
+
15
+ context "given a code max length of 10 has been set" do
16
+ before { subject.code_max_length = 10 }
17
+ its(:code_max_length) { should be 10 }
18
+ end
19
+
20
+ context "given a scope identifier max length of 11 has been set" do
21
+ before { subject.scope_identifier_max_length = 11 }
22
+ its(:scope_identifier_max_length) { should be 11 }
23
+ end
24
+
25
+ context "given an account identifier max length of 9 has been set" do
26
+ before { subject.account_identifier_max_length = 9 }
27
+ its(:account_identifier_max_length) { should be 9 }
28
+ end
29
+
30
+ after do
31
+ subject.code_max_length = nil
32
+ subject.scope_identifier_max_length = nil
33
+ subject.account_identifier_max_length = nil
34
+ end
35
+ end
36
+
8
37
  describe "#define_accounts" do
9
38
  it "yields the accounts set" do
10
39
  expect { |block|
@@ -6,7 +6,7 @@ describe DoubleEntry::Line do
6
6
  end
7
7
 
8
8
  describe "persistance" do
9
- let(:persisted_line) {
9
+ let(:line_to_persist) {
10
10
  DoubleEntry::Line.new(
11
11
  :amount => Money.new(10_00),
12
12
  :balance => Money.zero,
@@ -18,11 +18,13 @@ describe DoubleEntry::Line do
18
18
  let(:account) { DoubleEntry.account(:test, :scope => "17") }
19
19
  let(:partner_account) { DoubleEntry.account(:test, :scope => "72") }
20
20
  let(:code) { :test_code }
21
- subject { DoubleEntry::Line.last }
22
21
 
23
- describe "attributes" do
24
- before { persisted_line.save! }
22
+ subject(:persisted_line) do
23
+ line_to_persist.save!
24
+ line_to_persist.reload
25
+ end
25
26
 
27
+ describe "attributes" do
26
28
  context "given code = :the_code" do
27
29
  let(:code) { :the_code }
28
30
  its(:code) { should eq :the_code }
@@ -30,7 +32,7 @@ describe DoubleEntry::Line do
30
32
 
31
33
  context "given code = nil" do
32
34
  let(:code) { nil }
33
- its(:code) { should eq nil }
35
+ specify { expect { line_to_persist.save! }.to raise_error }
34
36
  end
35
37
 
36
38
  context "given account = :test, 54 " do
@@ -52,22 +54,20 @@ describe DoubleEntry::Line do
52
54
  end
53
55
  end
54
56
 
55
- describe '#save' do
56
- context 'when balance is sent negative' do
57
- let(:account) {
58
- DoubleEntry.account(:savings, :scope => '17', :positive_only => true)
59
- }
57
+ context 'when balance is sent negative' do
58
+ let(:account) {
59
+ DoubleEntry.account(:savings, :scope => '17', :positive_only => true)
60
+ }
60
61
 
61
- let(:line) {
62
- DoubleEntry::Line.new(
63
- :balance => Money.new(-1),
64
- :account => account,
65
- )
66
- }
62
+ let(:line) {
63
+ DoubleEntry::Line.new(
64
+ :balance => Money.new(-1),
65
+ :account => account,
66
+ )
67
+ }
67
68
 
68
- it 'raises AccountWouldBeSentNegative exception' do
69
- expect { line.save }.to raise_error DoubleEntry::AccountWouldBeSentNegative
70
- end
69
+ it 'raises AccountWouldBeSentNegative exception' do
70
+ expect { line.save }.to raise_error DoubleEntry::AccountWouldBeSentNegative
71
71
  end
72
72
  end
73
73
 
@@ -51,8 +51,20 @@ describe DoubleEntry::Locking do
51
51
  end
52
52
 
53
53
  it "takes the balance for new account balance records from the lines table" do
54
- DoubleEntry::Line.create!(:account => @account_a, :partner_account => @account_b, :amount => Money.new(3_00), :balance => Money.new( 3_00), :code => :test)
55
- DoubleEntry::Line.create!(:account => @account_a, :partner_account => @account_b, :amount => Money.new(7_00), :balance => Money.new(10_00), :code => :test)
54
+ DoubleEntry::Line.create!(
55
+ :account => @account_a,
56
+ :partner_account => @account_b,
57
+ :amount => Money.new(3_00),
58
+ :balance => Money.new(3_00),
59
+ :code => :test,
60
+ )
61
+ DoubleEntry::Line.create!(
62
+ :account => @account_a,
63
+ :partner_account => @account_b,
64
+ :amount => Money.new(7_00),
65
+ :balance => Money.new(10_00),
66
+ :code => :test,
67
+ )
56
68
 
57
69
  expect do
58
70
  DoubleEntry::Locking.lock_accounts(@account_a) { }
@@ -1,17 +1,38 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
- describe DoubleEntry::Transfer::Set do
4
- describe "#define" do
5
- before do
6
- subject.define(
7
- :code => "code",
8
- :from => double(:identifier => "from"),
9
- :to => double(:identifier => "to"),
10
- )
3
+ module DoubleEntry
4
+ describe Transfer do
5
+
6
+ describe "::new" do
7
+ context "given a code 47 characters in length" do
8
+ let(:code) { "xxxxxxxxxxxxxxxx 47 characters xxxxxxxxxxxxxxxx" }
9
+ specify do
10
+ expect { Transfer.new(:code => code) }.to_not raise_error
11
+ end
12
+ end
13
+
14
+ context "given a code 48 characters in length" do
15
+ let(:code) { "xxxxxxxxxxxxxxxx 48 characters xxxxxxxxxxxxxxxxx" }
16
+ specify do
17
+ expect { Transfer.new(:code => code) }.to raise_error TransferCodeTooLongError, /'#{code}'/
18
+ end
19
+ end
20
+ end
21
+
22
+ describe Transfer::Set do
23
+ describe "#define" do
24
+ before do
25
+ subject.define(
26
+ :code => "code",
27
+ :from => double(:identifier => "from"),
28
+ :to => double(:identifier => "to"),
29
+ )
30
+ end
31
+ its(:first) { should be_a Transfer }
32
+ its("first.code") { should eq "code" }
33
+ its("first.from.identifier") { should eq "from" }
34
+ its("first.to.identifier") { should eq "to" }
35
+ end
11
36
  end
12
- its(:first) { should be_a DoubleEntry::Transfer }
13
- its("first.code") { should eq "code" }
14
- its("first.from.identifier") { should eq "from" }
15
- its("first.to.identifier") { should eq "to" }
16
37
  end
17
38
  end
@@ -173,9 +173,8 @@ describe DoubleEntry do
173
173
  accounts.define(:identifier => :b)
174
174
  end
175
175
 
176
- description = ->(line) { "Money goes #{line.decrease? ? 'out' : 'in'}: #{line.amount.format}" }
177
176
  config.define_transfers do |transfers|
178
- transfers.define(:code => :xfer, :from => :a, :to => :b, :description => description)
177
+ transfers.define(:code => :xfer, :from => :a, :to => :b)
179
178
  end
180
179
  end
181
180
 
@@ -2,68 +2,63 @@ ActiveRecord::Schema.define do
2
2
  self.verbose = false
3
3
 
4
4
  create_table "double_entry_account_balances", :force => true do |t|
5
- t.string "account", :null => false
6
- t.string "scope"
7
- t.integer "balance"
8
- t.datetime "created_at"
9
- t.datetime "updated_at"
5
+ t.string "account", :limit => 31, :null => false
6
+ t.string "scope", :limit => 23
7
+ t.integer "balance", :null => false
8
+ t.timestamps
10
9
  end
11
10
 
12
- add_index "double_entry_account_balances", ["account"], :name => "index_account_balances_on_account"
11
+ add_index "double_entry_account_balances", ["account"], :name => "index_account_balances_on_account"
13
12
  add_index "double_entry_account_balances", ["scope", "account"], :name => "index_account_balances_on_scope_and_account", :unique => true
14
13
 
15
14
  create_table "double_entry_lines", :force => true do |t|
16
- t.string "account"
17
- t.string "scope"
18
- t.string "code"
19
- t.integer "amount"
20
- t.integer "balance"
21
- t.integer "partner_id"
22
- t.string "partner_account"
23
- t.string "partner_scope"
24
- t.integer "detail_id"
25
- t.string "detail_type"
26
- t.datetime "created_at"
27
- t.datetime "updated_at"
15
+ t.string "account", :limit => 31, :null => false
16
+ t.string "scope", :limit => 23
17
+ t.string "code", :limit => 47, :null => false
18
+ t.integer "amount", :null => false
19
+ t.integer "balance", :null => false
20
+ t.integer "partner_id"
21
+ t.string "partner_account", :limit => 31, :null => false
22
+ t.string "partner_scope", :limit => 23
23
+ t.integer "detail_id"
24
+ t.string "detail_type"
25
+ t.timestamps
28
26
  end
29
27
 
30
- add_index "double_entry_lines", ["account", "code", "created_at"], :name => "lines_account_code_created_at_idx"
31
- add_index "double_entry_lines", ["account", "created_at"], :name => "lines_account_created_at_idx"
28
+ add_index "double_entry_lines", ["account", "code", "created_at"], :name => "lines_account_code_created_at_idx"
29
+ add_index "double_entry_lines", ["account", "created_at"], :name => "lines_account_created_at_idx"
32
30
  add_index "double_entry_lines", ["scope", "account", "created_at"], :name => "lines_scope_account_created_at_idx"
33
- add_index "double_entry_lines", ["scope", "account", "id"], :name => "lines_scope_account_id_idx"
31
+ add_index "double_entry_lines", ["scope", "account", "id"], :name => "lines_scope_account_id_idx"
34
32
 
35
33
  create_table "double_entry_line_aggregates", :force => true do |t|
36
- t.string "function"
37
- t.string "account"
38
- t.string "code"
39
- t.string "scope"
40
- t.integer "year"
41
- t.integer "month"
42
- t.integer "week"
43
- t.integer "day"
44
- t.integer "hour"
45
- t.integer "amount"
46
- t.datetime "created_at"
47
- t.datetime "updated_at"
48
- t.string "filter"
49
- t.string "range_type"
34
+ t.string "function", :limit => 15, :null => false
35
+ t.string "account", :limit => 31, :null => false
36
+ t.string "code", :limit => 47
37
+ t.string "scope", :limit => 23
38
+ t.integer "year"
39
+ t.integer "month"
40
+ t.integer "week"
41
+ t.integer "day"
42
+ t.integer "hour"
43
+ t.integer "amount", :null => false
44
+ t.string "filter"
45
+ t.string "range_type", :limit => 15, :null => false
46
+ t.timestamps
50
47
  end
51
48
 
52
49
  add_index "double_entry_line_aggregates", ["function", "account", "code", "year", "month", "week", "day"], :name => "line_aggregate_idx"
53
50
 
54
51
  create_table "double_entry_line_checks", :force => true do |t|
55
- t.integer "last_line_id"
56
- t.boolean "errors_found"
57
- t.text "log"
58
- t.datetime "created_at"
59
- t.datetime "updated_at"
52
+ t.integer "last_line_id", :null => false
53
+ t.boolean "errors_found", :null => false
54
+ t.text "log"
55
+ t.timestamps
60
56
  end
61
57
 
62
58
  # test table only
63
59
  create_table "users", :force => true do |t|
64
- t.string "username"
65
- t.datetime "created_at"
66
- t.datetime "updated_at"
60
+ t.string "username", :null => false
61
+ t.timestamps
67
62
  end
68
63
 
69
64
  add_index "users", ["username"], :name => "index_users_on_username", :unique => true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: double_entry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Sellitti
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2014-11-19 00:00:00.000000000 Z
18
+ date: 2014-12-08 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: money