class DoubleEntry::Reporting::Aggregate

Attributes

account[R]
code[R]
currency[R]
filter[R]
function[R]
partner_account[R]
range[R]

Public Class Methods

formatted_amount(function:, account:, code:, range:, partner_account: nil, filter: nil) click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 7
def self.formatted_amount(function:, account:, code:, range:, partner_account: nil, filter: nil)
  new(
    function: function,
    account: account,
    code: code,
    range: range,
    partner_account: partner_account,
    filter: filter,
  ).formatted_amount
end
new(function:, account:, code:, range:, partner_account: nil, filter: nil) click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 18
def initialize(function:, account:, code:, range:, partner_account: nil, filter: nil)
  @function = function.to_s
  fail AggregateFunctionNotSupported unless %w(sum count average).include?(@function)

  @account         = account
  @code            = code.try(:to_s)
  @range           = range
  @partner_account = partner_account
  @filter          = filter
  @currency        = DoubleEntry::Account.currency(account)
end

Public Instance Methods

amount(force_recalculation = false) click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 30
def amount(force_recalculation = false)
  if force_recalculation
    clear_old_aggregates
    calculate
  else
    retrieve || calculate
  end
end
formatted_amount(value = amount) click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 39
def formatted_amount(value = amount)
  value ||= 0
  if function == 'count'
    value
  else
    Money.new(value, currency)
  end
end

Private Instance Methods

calculate() click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 59
def calculate
  if range.class == YearRange
    aggregate = calculate_yearly_aggregate
  else
    aggregate = LineAggregate.aggregate(
      function: function,
      account: account,
      partner_account: partner_account,
      code: code,
      range: range,
      named_scopes: filter
    )
  end

  if range_is_complete?
    fields = field_hash
    fields[:amount] = aggregate || 0
    LineAggregate.create! fields
  end

  aggregate
end
calculate_yearly_aggregate() click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 82
def calculate_yearly_aggregate
  # We calculate yearly aggregates by combining monthly aggregates
  # otherwise they will get excruciatingly slow to calculate
  # as the year progresses.  (I am thinking mainly of the 'current' year.)
  # Combining monthly aggregates will mean that the figure will be partially memoized
  if function == 'average'
    calculate_yearly_average
  else
    result = (1..12).inject(formatted_amount(0)) do |total, month|
      total + Aggregate.new(function: function, account: account, code: code,
                            range: MonthRange.new(:year => range.year, :month => month),
                            partner_account: partner_account, filter: filter).formatted_amount
    end
    result.is_a?(Money) ? result.cents : result
  end
end
calculate_yearly_average() click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 99
def calculate_yearly_average
  # need this seperate function, because an average of averages is not the correct average
  year_range = YearRange.new(:year => range.year)
  sum = Aggregate.new(function: :sum, account: account, code: code, range: year_range,
                      partner_account: partner_account, filter: filter).formatted_amount
  count = Aggregate.new(function: :count, account: account, code: code, range: year_range,
                        partner_account: partner_account, filter: filter).formatted_amount
  (count == 0) ? 0 : (sum / count).cents
end
clear_old_aggregates() click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 55
def clear_old_aggregates
  LineAggregate.delete_all(field_hash)
end
field_hash() click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 113
def field_hash
  {
    :function        => function,
    :account         => account,
    :partner_account => partner_account,
    :code            => code,
    :year            => range.year,
    :month           => range.month,
    :week            => range.week,
    :day             => range.day,
    :hour            => range.hour,
    :filter          => filter.inspect,
    :range_type      => range.range_type.to_s,
  }
end
range_is_complete?() click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 109
def range_is_complete?
  Time.now > range.finish
end
retrieve() click to toggle source
# File lib/double_entry/reporting/aggregate.rb, line 50
def retrieve
  aggregate = LineAggregate.where(field_hash).first
  aggregate.amount if aggregate
end