Module: Twobook
- Defined in:
- lib/twobook/entry.rb,
lib/twobook/event.rb,
lib/twobook/account.rb,
lib/twobook/handler.rb,
lib/twobook/helpers.rb,
lib/twobook/version.rb,
lib/twobook/agreement.rb,
lib/twobook/utilities.rb,
lib/twobook/corrections.rb,
lib/twobook/account_query.rb,
lib/twobook/configuration.rb,
lib/twobook/serialization.rb,
lib/twobook/number_handling.rb,
lib/twobook/event_processing.rb,
lib/twobook/handler/query_helpers.rb,
lib/twobook/handler/booking_helpers.rb
Defined Under Namespace
Modules: Corrections, Helpers, Serialization, Utilities
Classes: Account, AccountQuery, Agreement, Configuration, Entry, Event, Handler
Constant Summary
collapse
- VERSION =
'0.1.4'
- PRECISION =
15
- SCALE =
6
Class Method Summary
collapse
Class Method Details
.configuration ⇒ Object
6
7
8
|
# File 'lib/twobook/configuration.rb', line 6
def self.configuration
@configuration
end
|
10
11
12
13
|
# File 'lib/twobook/configuration.rb', line 10
def self.configure
@configuration ||= Configuration.new
yield(@configuration)
end
|
.ensure_transaction!(accounts, event) ⇒ Object
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
# File 'lib/twobook/event_processing.rb', line 39
def self.ensure_transaction!(accounts, event)
assets = sum_entries_under_account_type(:assets, accounts, event)
liabilities = sum_entries_under_account_type(:liabilities, accounts, event)
revenue = sum_entries_under_account_type(:revenue, accounts, event)
expenses = sum_entries_under_account_type(:expenses, accounts, event)
sum = assets - liabilities - revenue + expenses
if sum.nonzero?
report = accounts.map do |a|
"#{a.name}: #{a.entries.select { |e| e.event == event }.map(&:amount).sum}"
end.join("\n")
raise "Invalid transaction: must sum to zero, but summed to #{sum}. \n#{report}"
end
end
|
.simulate(event, input_accounts = []) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# File 'lib/twobook/event_processing.rb', line 2
def self.simulate(event, input_accounts = [])
return simulate_chain(event, input_accounts) if event.is_a?(Array)
raise 'Cannot simulate: event has no agreements' unless event.agreements.any?
handlers = event.agreements.reduce([]) do |memo, agreement|
memo + agreement.handlers_for(event)
end
new_accounts = handlers.reduce(Set.new(input_accounts)) do |processing_accounts, handler|
handler.run(processing_accounts)
end
ensure_transaction! new_accounts, event
new_accounts
end
|
.simulate_chain(events, input_accounts = []) ⇒ Object
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
# File 'lib/twobook/event_processing.rb', line 20
def self.simulate_chain(events, input_accounts = [])
sorted_groups = events.group_by(&:happened_at)
sorted = []
sorted_groups.keys.sort.each do |time|
group = sorted_groups[time]
sorted_group = if group.any? { |event| event.partial_order.nil? }
group.map.with_index { |event, i| event.update_partial_order(i) }
else
group.sort_by(&:partial_order)
end
sorted_group.each { |event| sorted << event }
end
sorted.reduce(input_accounts) do |accounts, event|
simulate(event, accounts)
end
end
|
.sum_entries_under_account_type(type, accounts, event) ⇒ Object
56
57
58
59
60
|
# File 'lib/twobook/event_processing.rb', line 56
def self.sum_entries_under_account_type(type, accounts, event)
accounts.select { |a| a.class.account_type == type }.map do |a|
a.entries.select { |e| e.event == event }.map(&:amount).sum
end.sum
end
|
.where(**conditions) ⇒ Object
2
3
4
|
# File 'lib/twobook/helpers.rb', line 2
def self.where(**conditions)
AccountQuery.where(**conditions)
end
|
.wrap_number(n) ⇒ Object
19
20
21
|
# File 'lib/twobook/number_handling.rb', line 19
def self.wrap_number(n)
::BigDecimal.new(n, PRECISION).round(SCALE)
end
|