double_entry 1.0.1 → 2.0.0.beta1
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +432 -0
- data/README.md +36 -9
- data/double_entry.gemspec +20 -48
- data/lib/active_record/locking_extensions.rb +3 -3
- data/lib/active_record/locking_extensions/log_subscriber.rb +1 -1
- data/lib/double_entry/account.rb +38 -45
- data/lib/double_entry/account_balance.rb +18 -1
- data/lib/double_entry/errors.rb +13 -13
- data/lib/double_entry/line.rb +3 -2
- data/lib/double_entry/reporting.rb +26 -38
- data/lib/double_entry/reporting/aggregate.rb +43 -23
- data/lib/double_entry/reporting/aggregate_array.rb +16 -13
- data/lib/double_entry/reporting/line_aggregate.rb +3 -2
- data/lib/double_entry/reporting/line_aggregate_filter.rb +8 -10
- data/lib/double_entry/reporting/line_metadata_filter.rb +33 -0
- data/lib/double_entry/transfer.rb +33 -27
- data/lib/double_entry/validation.rb +1 -0
- data/lib/double_entry/validation/account_fixer.rb +36 -0
- data/lib/double_entry/validation/line_check.rb +22 -40
- data/lib/double_entry/version.rb +1 -1
- data/lib/generators/double_entry/install/install_generator.rb +7 -1
- data/lib/generators/double_entry/install/templates/migration.rb +27 -25
- metadata +33 -243
- data/.gitignore +0 -32
- data/.rspec +0 -2
- data/.travis.yml +0 -29
- data/.yardopts +0 -2
- data/Gemfile +0 -2
- data/Rakefile +0 -15
- data/script/jack_hammer +0 -210
- data/script/setup.sh +0 -8
- data/spec/active_record/locking_extensions_spec.rb +0 -110
- data/spec/double_entry/account_balance_spec.rb +0 -7
- data/spec/double_entry/account_spec.rb +0 -130
- data/spec/double_entry/balance_calculator_spec.rb +0 -88
- data/spec/double_entry/configuration_spec.rb +0 -50
- data/spec/double_entry/line_spec.rb +0 -80
- data/spec/double_entry/locking_spec.rb +0 -214
- data/spec/double_entry/performance/double_entry_performance_spec.rb +0 -32
- data/spec/double_entry/performance/reporting/aggregate_performance_spec.rb +0 -50
- data/spec/double_entry/reporting/aggregate_array_spec.rb +0 -123
- data/spec/double_entry/reporting/aggregate_spec.rb +0 -205
- data/spec/double_entry/reporting/line_aggregate_filter_spec.rb +0 -90
- data/spec/double_entry/reporting/line_aggregate_spec.rb +0 -39
- data/spec/double_entry/reporting/month_range_spec.rb +0 -139
- data/spec/double_entry/reporting/time_range_array_spec.rb +0 -169
- data/spec/double_entry/reporting/time_range_spec.rb +0 -45
- data/spec/double_entry/reporting/week_range_spec.rb +0 -103
- data/spec/double_entry/reporting_spec.rb +0 -181
- data/spec/double_entry/transfer_spec.rb +0 -93
- data/spec/double_entry/validation/line_check_spec.rb +0 -99
- data/spec/double_entry_spec.rb +0 -428
- data/spec/generators/double_entry/install/install_generator_spec.rb +0 -30
- data/spec/spec_helper.rb +0 -118
- data/spec/support/accounts.rb +0 -21
- data/spec/support/blueprints.rb +0 -43
- data/spec/support/database.example.yml +0 -21
- data/spec/support/database.travis.yml +0 -24
- data/spec/support/double_entry_spec_helper.rb +0 -27
- data/spec/support/gemfiles/Gemfile.rails-3.2.x +0 -8
- data/spec/support/gemfiles/Gemfile.rails-4.1.x +0 -6
- data/spec/support/gemfiles/Gemfile.rails-4.2.x +0 -5
- data/spec/support/gemfiles/Gemfile.rails-5.0.x +0 -5
- data/spec/support/performance_helper.rb +0 -26
- data/spec/support/reporting_configuration.rb +0 -6
- data/spec/support/schema.rb +0 -74
@@ -2,21 +2,29 @@
|
|
2
2
|
module DoubleEntry
|
3
3
|
module Reporting
|
4
4
|
class Aggregate
|
5
|
-
attr_reader :function, :account, :code, :range, :filter, :currency
|
5
|
+
attr_reader :function, :account, :partner_account, :code, :range, :filter, :currency
|
6
6
|
|
7
|
-
def self.formatted_amount(function
|
8
|
-
new(
|
7
|
+
def self.formatted_amount(function:, account:, code:, range:, partner_account: nil, filter: nil)
|
8
|
+
new(
|
9
|
+
function: function,
|
10
|
+
account: account,
|
11
|
+
code: code,
|
12
|
+
range: range,
|
13
|
+
partner_account: partner_account,
|
14
|
+
filter: filter,
|
15
|
+
).formatted_amount
|
9
16
|
end
|
10
17
|
|
11
|
-
def initialize(function
|
18
|
+
def initialize(function:, account:, code:, range:, partner_account: nil, filter: nil)
|
12
19
|
@function = function.to_s
|
13
20
|
fail AggregateFunctionNotSupported unless %w(sum count average).include?(@function)
|
14
21
|
|
15
|
-
@account
|
16
|
-
@code
|
17
|
-
@range
|
18
|
-
@
|
19
|
-
@
|
22
|
+
@account = account
|
23
|
+
@code = code.try(:to_s)
|
24
|
+
@range = range
|
25
|
+
@partner_account = partner_account
|
26
|
+
@filter = filter
|
27
|
+
@currency = DoubleEntry::Account.currency(account)
|
20
28
|
end
|
21
29
|
|
22
30
|
def amount(force_recalculation = false)
|
@@ -52,7 +60,14 @@ module DoubleEntry
|
|
52
60
|
if range.class == YearRange
|
53
61
|
aggregate = calculate_yearly_aggregate
|
54
62
|
else
|
55
|
-
aggregate = LineAggregate.aggregate(
|
63
|
+
aggregate = LineAggregate.aggregate(
|
64
|
+
function: function,
|
65
|
+
account: account,
|
66
|
+
partner_account: partner_account,
|
67
|
+
code: code,
|
68
|
+
range: range,
|
69
|
+
named_scopes: filter
|
70
|
+
)
|
56
71
|
end
|
57
72
|
|
58
73
|
if range_is_complete?
|
@@ -73,7 +88,9 @@ module DoubleEntry
|
|
73
88
|
calculate_yearly_average
|
74
89
|
else
|
75
90
|
result = (1..12).inject(formatted_amount(0)) do |total, month|
|
76
|
-
total + Aggregate.new(function, account
|
91
|
+
total + Aggregate.new(function: function, account: account, code: code,
|
92
|
+
range: MonthRange.new(:year => range.year, :month => month),
|
93
|
+
partner_account: partner_account, filter: filter).formatted_amount
|
77
94
|
end
|
78
95
|
result.is_a?(Money) ? result.cents : result
|
79
96
|
end
|
@@ -82,8 +99,10 @@ module DoubleEntry
|
|
82
99
|
def calculate_yearly_average
|
83
100
|
# need this seperate function, because an average of averages is not the correct average
|
84
101
|
year_range = YearRange.new(:year => range.year)
|
85
|
-
sum = Aggregate.new(:sum, account, code
|
86
|
-
|
102
|
+
sum = Aggregate.new(function: :sum, account: account, code: code, range: year_range,
|
103
|
+
partner_account: partner_account, filter: filter).formatted_amount
|
104
|
+
count = Aggregate.new(function: :count, account: account, code: code, range: year_range,
|
105
|
+
partner_account: partner_account, filter: filter).formatted_amount
|
87
106
|
(count == 0) ? 0 : (sum / count).cents
|
88
107
|
end
|
89
108
|
|
@@ -93,16 +112,17 @@ module DoubleEntry
|
|
93
112
|
|
94
113
|
def field_hash
|
95
114
|
{
|
96
|
-
:function
|
97
|
-
:account
|
98
|
-
:
|
99
|
-
:
|
100
|
-
:
|
101
|
-
:
|
102
|
-
:
|
103
|
-
:
|
104
|
-
:
|
105
|
-
:
|
115
|
+
:function => function,
|
116
|
+
:account => account,
|
117
|
+
:partner_account => partner_account,
|
118
|
+
:code => code,
|
119
|
+
:year => range.year,
|
120
|
+
:month => range.month,
|
121
|
+
:week => range.week,
|
122
|
+
:day => range.day,
|
123
|
+
:hour => range.hour,
|
124
|
+
:filter => filter.inspect,
|
125
|
+
:range_type => range.range_type.to_s,
|
106
126
|
}
|
107
127
|
end
|
108
128
|
end
|
@@ -9,17 +9,18 @@ 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, :currency
|
12
|
+
attr_reader :function, :account, :partner_account, :code, :filter, :range_type, :start, :finish, :currency
|
13
13
|
|
14
|
-
def initialize(function
|
15
|
-
@function
|
16
|
-
@account
|
17
|
-
@code
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@
|
14
|
+
def initialize(function:, account:, code:, partner_account: nil, filter: nil, range_type: nil, start: nil, finish: nil)
|
15
|
+
@function = function.to_s
|
16
|
+
@account = account
|
17
|
+
@code = code
|
18
|
+
@partner_account = partner_account
|
19
|
+
@filter = filter
|
20
|
+
@range_type = range_type
|
21
|
+
@start = start
|
22
|
+
@finish = finish
|
23
|
+
@currency = DoubleEntry::Account.currency(account)
|
23
24
|
|
24
25
|
retrieve_aggregates
|
25
26
|
fill_in_missing_aggregates
|
@@ -39,7 +40,8 @@ module DoubleEntry
|
|
39
40
|
# (this includes aggregates for the still-running period)
|
40
41
|
all_periods.each do |period|
|
41
42
|
unless @aggregates[period.key]
|
42
|
-
@aggregates[period.key] = Aggregate.formatted_amount(function, account, code
|
43
|
+
@aggregates[period.key] = Aggregate.formatted_amount(function: function, account: account, code: code,
|
44
|
+
range: period, partner_account: partner_account, filter: filter)
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
@@ -50,8 +52,9 @@ module DoubleEntry
|
|
50
52
|
scope = LineAggregate.
|
51
53
|
where(:function => function).
|
52
54
|
where(:range_type => 'normal').
|
53
|
-
where(:account => account.to_s).
|
54
|
-
where(:
|
55
|
+
where(:account => account.try(:to_s)).
|
56
|
+
where(:partner_account => partner_account.try(:to_s)).
|
57
|
+
where(:code => code.try(:to_s)).
|
55
58
|
where(:filter => filter.inspect).
|
56
59
|
where(LineAggregate.arel_table[range_type].not_eq(nil))
|
57
60
|
@aggregates = scope.each_with_object({}) do |result, hash|
|
@@ -2,8 +2,9 @@
|
|
2
2
|
module DoubleEntry
|
3
3
|
module Reporting
|
4
4
|
class LineAggregate < ActiveRecord::Base
|
5
|
-
def self.aggregate(function
|
6
|
-
collection_filter = LineAggregateFilter.new(account
|
5
|
+
def self.aggregate(function:, account:, partner_account:, code:, range:, named_scopes:)
|
6
|
+
collection_filter = LineAggregateFilter.new(account: account, partner_account: partner_account,
|
7
|
+
code: code, range: range, filter_criteria: named_scopes)
|
7
8
|
collection = collection_filter.filter
|
8
9
|
collection.send(function, :amount)
|
9
10
|
end
|
@@ -2,8 +2,10 @@
|
|
2
2
|
module DoubleEntry
|
3
3
|
module Reporting
|
4
4
|
class LineAggregateFilter
|
5
|
-
|
5
|
+
|
6
|
+
def initialize(account:, partner_account:, code:, range:, filter_criteria:)
|
6
7
|
@account = account
|
8
|
+
@partner_account = partner_account
|
7
9
|
@code = code
|
8
10
|
@range = range
|
9
11
|
@filter_criteria = filter_criteria || []
|
@@ -20,6 +22,7 @@ module DoubleEntry
|
|
20
22
|
where(:account => @account).
|
21
23
|
where(:created_at => @range.start..@range.finish)
|
22
24
|
collection = collection.where(:code => @code) if @code
|
25
|
+
collection = collection.where(:partner_account => @partner_account) if @partner_account
|
23
26
|
|
24
27
|
collection
|
25
28
|
end
|
@@ -42,10 +45,11 @@ module DoubleEntry
|
|
42
45
|
# :name => :ten_dollar_purchases
|
43
46
|
# }
|
44
47
|
# },
|
45
|
-
# # an example of providing
|
48
|
+
# # an example of providing multiple metadatum criteria to filter on
|
46
49
|
# {
|
47
50
|
# :metadata => {
|
48
|
-
# :meme => :business_cat
|
51
|
+
# :meme => :business_cat,
|
52
|
+
# :category => :fun_times,
|
49
53
|
# }
|
50
54
|
# }
|
51
55
|
# ]
|
@@ -66,13 +70,7 @@ module DoubleEntry
|
|
66
70
|
end
|
67
71
|
|
68
72
|
def filter_by_metadata(collection, metadata)
|
69
|
-
|
70
|
-
filtered_collection.where(metadata_table => { :key => key, :value => value })
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def metadata_table
|
75
|
-
DoubleEntry::LineMetadata.table_name.to_sym
|
73
|
+
DoubleEntry::Reporting::LineMetadataFilter.filter(collection: collection, metadata: metadata)
|
76
74
|
end
|
77
75
|
end
|
78
76
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module DoubleEntry
|
3
|
+
module Reporting
|
4
|
+
class LineMetadataFilter
|
5
|
+
|
6
|
+
def self.filter(collection:, metadata:)
|
7
|
+
table_alias_index = 0
|
8
|
+
|
9
|
+
metadata.reduce(collection) do |filtered_collection, (key, value)|
|
10
|
+
table_alias = "m#{table_alias_index}"
|
11
|
+
table_alias_index += 1
|
12
|
+
|
13
|
+
filtered_collection.
|
14
|
+
joins("INNER JOIN #{line_metadata_table} as #{table_alias} ON #{table_alias}.line_id = #{lines_table}.id").
|
15
|
+
where("#{table_alias}.key = ? AND #{table_alias}.value = ?", key, value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def self.line_metadata_table
|
22
|
+
DoubleEntry::LineMetadata.table_name
|
23
|
+
end
|
24
|
+
private_class_method :line_metadata_table
|
25
|
+
|
26
|
+
def self.lines_table
|
27
|
+
DoubleEntry::Line.table_name
|
28
|
+
end
|
29
|
+
private_class_method :lines_table
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,19 +1,17 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require 'forwardable'
|
3
|
+
|
2
4
|
module DoubleEntry
|
3
5
|
class Transfer
|
4
6
|
class << self
|
5
|
-
|
7
|
+
attr_accessor :code_max_length
|
8
|
+
attr_writer :transfers
|
6
9
|
|
7
10
|
# @api private
|
8
11
|
def transfers
|
9
12
|
@transfers ||= Set.new
|
10
13
|
end
|
11
14
|
|
12
|
-
# @api private
|
13
|
-
def code_max_length
|
14
|
-
@code_max_length ||= 47
|
15
|
-
end
|
16
|
-
|
17
15
|
# @api private
|
18
16
|
def transfer(amount, options = {})
|
19
17
|
fail TransferIsNegative if amount.negative?
|
@@ -25,37 +23,43 @@ module DoubleEntry
|
|
25
23
|
end
|
26
24
|
|
27
25
|
# @api private
|
28
|
-
class Set
|
26
|
+
class Set
|
27
|
+
extend Forwardable
|
28
|
+
delegate [:each, :map] => :all
|
29
|
+
|
29
30
|
def define(attributes)
|
30
|
-
|
31
|
+
Transfer.new(attributes).tap do |transfer|
|
32
|
+
key = [transfer.from, transfer.to, transfer.code]
|
33
|
+
if _find(*key)
|
34
|
+
fail DuplicateTransfer
|
35
|
+
else
|
36
|
+
backing_collection[key] = transfer
|
37
|
+
end
|
38
|
+
end
|
31
39
|
end
|
32
40
|
|
33
|
-
def find(
|
34
|
-
_find(
|
41
|
+
def find(from_account, to_account, code)
|
42
|
+
_find(from_account.identifier, to_account.identifier, code)
|
35
43
|
end
|
36
44
|
|
37
|
-
def find!(
|
38
|
-
find(
|
39
|
-
fail TransferNotAllowed, [
|
45
|
+
def find!(from_account, to_account, code)
|
46
|
+
find(from_account, to_account, code).tap do |transfer|
|
47
|
+
fail TransferNotAllowed, [from_account.identifier, to_account.identifier, code].inspect unless transfer
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
43
|
-
def
|
44
|
-
|
45
|
-
fail DuplicateTransfer
|
46
|
-
else
|
47
|
-
super(transfer)
|
48
|
-
end
|
51
|
+
def all
|
52
|
+
backing_collection.values
|
49
53
|
end
|
50
54
|
|
51
55
|
private
|
52
56
|
|
57
|
+
def backing_collection
|
58
|
+
@backing_collection ||= Hash.new
|
59
|
+
end
|
60
|
+
|
53
61
|
def _find(from, to, code)
|
54
|
-
|
55
|
-
transfer.from == from &&
|
56
|
-
transfer.to == to &&
|
57
|
-
transfer.code == code
|
58
|
-
end
|
62
|
+
backing_collection[[from, to, code]]
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
@@ -65,7 +69,7 @@ module DoubleEntry
|
|
65
69
|
@code = attributes[:code]
|
66
70
|
@from = attributes[:from]
|
67
71
|
@to = attributes[:to]
|
68
|
-
if code.length > Transfer.code_max_length
|
72
|
+
if Transfer.code_max_length && code.length > Transfer.code_max_length
|
69
73
|
fail TransferCodeTooLongError,
|
70
74
|
"transfer code '#{code}' is too long. Please limit it to #{Transfer.code_max_length} characters."
|
71
75
|
end
|
@@ -115,8 +119,10 @@ module DoubleEntry
|
|
115
119
|
|
116
120
|
def create_line_metadata(credit, debit, metadata)
|
117
121
|
metadata.each_pair do |key, value|
|
118
|
-
|
119
|
-
|
122
|
+
Array(value).each do |each_value|
|
123
|
+
LineMetadata.create!(:line => credit, :key => key, :value => each_value)
|
124
|
+
LineMetadata.create!(:line => debit, :key => key, :value => each_value)
|
125
|
+
end
|
120
126
|
end
|
121
127
|
end
|
122
128
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DoubleEntry
|
4
|
+
module Validation
|
5
|
+
class AccountFixer
|
6
|
+
def recalculate_account(account)
|
7
|
+
DoubleEntry.lock_accounts(account) do
|
8
|
+
recalculated_balance = Money.zero(account.currency)
|
9
|
+
|
10
|
+
lines_for_account(account).each do |line|
|
11
|
+
recalculated_balance += line.amount
|
12
|
+
if line.balance != recalculated_balance
|
13
|
+
line.update_attribute(:balance, recalculated_balance)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
update_balance_for_account(account, recalculated_balance)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def lines_for_account(account)
|
24
|
+
Line.where(
|
25
|
+
account: account.identifier.to_s,
|
26
|
+
scope: account.scope_identity.to_s
|
27
|
+
).order(:id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def update_balance_for_account(account, balance)
|
31
|
+
account_balance = Locking.balance_for_locked_account(account)
|
32
|
+
account_balance.update_attribute(:balance, balance)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -4,13 +4,16 @@ require 'set'
|
|
4
4
|
module DoubleEntry
|
5
5
|
module Validation
|
6
6
|
class LineCheck < ActiveRecord::Base
|
7
|
-
default_scope -> { order('created_at') }
|
8
7
|
|
9
|
-
def self.
|
10
|
-
|
8
|
+
def self.last_line_id_checked
|
9
|
+
order('created_at DESC').limit(1).pluck(:last_line_id).first || 0
|
11
10
|
end
|
12
11
|
|
13
|
-
def perform
|
12
|
+
def self.perform!(fixer: nil)
|
13
|
+
new.perform(fixer: fixer)
|
14
|
+
end
|
15
|
+
|
16
|
+
def perform(fixer: nil)
|
14
17
|
log = ''
|
15
18
|
current_line_id = nil
|
16
19
|
|
@@ -24,10 +27,10 @@ module DoubleEntry
|
|
24
27
|
end
|
25
28
|
|
26
29
|
active_accounts.each do |account|
|
27
|
-
incorrect_accounts << account
|
30
|
+
incorrect_accounts << account unless cached_balance_correct?(account, log)
|
28
31
|
end
|
29
32
|
|
30
|
-
incorrect_accounts.each
|
33
|
+
incorrect_accounts.each(&fixer.method(:recalculate_account)) if fixer
|
31
34
|
|
32
35
|
unless active_accounts.empty?
|
33
36
|
LineCheck.create!(
|
@@ -40,13 +43,8 @@ module DoubleEntry
|
|
40
43
|
|
41
44
|
private
|
42
45
|
|
43
|
-
def last_run_line_id
|
44
|
-
latest = LineCheck.last
|
45
|
-
latest ? latest.last_line_id : 0
|
46
|
-
end
|
47
|
-
|
48
46
|
def new_lines_since_last_run
|
49
|
-
Line.
|
47
|
+
Line.with_id_greater_than(LineCheck.last_line_id_checked)
|
50
48
|
end
|
51
49
|
|
52
50
|
def running_balance_correct?(line, log)
|
@@ -88,39 +86,23 @@ module DoubleEntry
|
|
88
86
|
#{previous_line.inspect}
|
89
87
|
#{line.inspect}
|
90
88
|
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
def cached_balance_correct?(account)
|
95
|
-
DoubleEntry.lock_accounts(account) do
|
96
|
-
return AccountBalance.find_by_account(account).balance == account.balance
|
97
|
-
end
|
89
|
+
END_OF_MESSAGE
|
98
90
|
end
|
99
91
|
|
100
|
-
def
|
92
|
+
def cached_balance_correct?(account, log)
|
101
93
|
DoubleEntry.lock_accounts(account) do
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
94
|
+
cached_balance = AccountBalance.find_by_account(account).balance
|
95
|
+
running_balance = account.balance
|
96
|
+
correct = (cached_balance == running_balance)
|
97
|
+
log << <<~MESSAGE unless correct
|
98
|
+
*********************************
|
99
|
+
Error on account #{account}: #{cached_balance} (cached balance) != #{running_balance} (running balance)
|
100
|
+
*********************************
|
101
|
+
|
102
|
+
MESSAGE
|
103
|
+
return correct
|
110
104
|
end
|
111
105
|
end
|
112
|
-
|
113
|
-
def lines_for_account(account)
|
114
|
-
Line.where(
|
115
|
-
:account => account.identifier.to_s,
|
116
|
-
:scope => account.scope_identity.to_s,
|
117
|
-
).order(:id)
|
118
|
-
end
|
119
|
-
|
120
|
-
def update_balance_for_account(account, balance)
|
121
|
-
account_balance = Locking.balance_for_locked_account(account)
|
122
|
-
account_balance.update_attribute(:balance, balance)
|
123
|
-
end
|
124
106
|
end
|
125
107
|
end
|
126
108
|
end
|