<commit_before># encoding: utf-8
module DoubleEntry
  class BalanceCalculator

    def initialize(account, scope, from, to, at, codes)
      if account.is_a? Symbol
        @account = account.to_s
        @scope = scope ? scope.id.to_s : nil
      else
        @account = account.identifier.to_s
        @scope = account.scope_identity
      end

      @from = from
      @to = to
      @codes = codes
    end


    def self.calculate(account, args = {})
      codes = (args[:codes].to_a << args[:code]).compact
      calculator = BalanceCalculator.new(account, args[:scope], args[:from], args[:to], args[:at], codes)
      calculator.calculate
    end

    def calculate
      lines = Line.where(:account => account)
      lines = lines.where('created_at <= ?', at) if scope_by_created_at_before?
      lines = lines.where('created_at >= ? and created_at <= ?', from, to) if scope_by_created_at_between?
      lines = lines.where(:code => codes) if scope_by_code?
      lines = lines.where(:scope => scope) if scope_by_scope?

      if lookup_via_created_at_range_or_code?
        # from and to or code lookups have to be done via sum
        Money.new(lines.sum(:amount))
      else
        # all other lookups can be performed with running balances
        line = Line.select("id, balance").from("#{Line.quoted_table_name} #{use_index}").where(conditions).order('id desc').first
        line ? line.balance : Money.empty
      end
    end

  private

    attr_reader :account, :scope, :from, :to, :at, :codes

    def scope_by_created_at_before?
      !!at
    end

    def scope_by_created_at_between?
      !!(from && to)
    end

    def scope_by_code?
      codes.present?
    end

    def scope_by_scope?
      !!scope
    end

    def lookup_via_created_at_range_or_code?
      (from && to) || codes
    end

    def use_index?
      # This is to work around a MySQL 5.1 query optimiser bug that causes the ORDER BY
      # on the query to fail in some circumstances, resulting in an old balance being
      # returned. This was biting us intermittently in spec runs.
      # See http://bugs.mysql.com/bug.php?id=51431
      Line.connection.adapter_name.match /mysql/i

      #"USE INDEX (lines_scope_account_id_idx)"
    end

  end
end<commit_msg>apparently we need to use this index<commit_after># encoding: utf-8
module DoubleEntry
  class BalanceCalculator

    def initialize(account, scope, from, to, at, codes)
      if account.is_a? Symbol
        @account = account.to_s
        @scope = scope ? scope.id.to_s : nil
      else
        @account = account.identifier.to_s
        @scope = account.scope_identity
      end

      @from = from
      @to = to
      @codes = codes
    end


    def self.calculate(account, args = {})
      codes = (args[:codes].to_a << args[:code]).compact
      calculator = BalanceCalculator.new(account, args[:scope], args[:from], args[:to], args[:at], codes)
      calculator.calculate
    end

    def calculate
      lines = Line.where(:account => account)
      lines = lines.where('created_at <= ?', at) if scope_by_created_at_before?
      lines = lines.where('created_at >= ? and created_at <= ?', from, to) if scope_by_created_at_between?
      lines = lines.where(:code => codes) if scope_by_code?
      lines = lines.where(:scope => scope) if scope_by_scope?

      if lookup_via_created_at_range_or_code?
        # from and to or code lookups have to be done via sum
        Money.new(lines.sum(:amount))
      else
        # all other lookups can be performed with running balances
        line = lines.select("id, balance").from(lines_table_name).order('id desc').first
        line ? line.balance : Money.empty
      end
    end

  private

    attr_reader :account, :scope, :from, :to, :at, :codes

    def scope_by_created_at_before?
      !!at
    end

    def scope_by_created_at_between?
      !!(from && to)
    end

    def scope_by_code?
      codes.present?
    end

    def scope_by_scope?
      !!scope
    end

    def lookup_via_created_at_range_or_code?
      (from && to) || codes
    end

    def use_index?
      # This is to work around a MySQL 5.1 query optimiser bug that causes the ORDER BY
      # on the query to fail in some circumstances, resulting in an old balance being
      # returned. This was biting us intermittently in spec runs.
      # See http://bugs.mysql.com/bug.php?id=51431
      Line.connection.adapter_name.match /mysql/i
    end

    def lines_table_name
      "#{Line.quoted_table_name} #{'USE INDEX (lines_scope_account_id_idx)' if use_index?}"
    end

  end
end
{'fraction_non_alphanumeric': 0.10080909687294992, 'fraction_numerical': 0.0034987972884321017, 'mean_word_length': 2.6562749800159873, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4877097', 'n_tokens_mistral': 1458, 'n_tokens_neox': 1398, 'n_words': 402}