<commit_before>class Chargeback < ActsAsArModel
  set_columns_hash( # Fields common to any chargeback type
    :start_date           => :datetime,
    :end_date             => :datetime,
    :interval_name        => :string,
    :display_range        => :string,
    :chargeback_rates     => :string,
    :entity               => :binary,
    :tag_name             => :string,
    :label_name           => :string,
    :fixed_compute_metric => :integer,
    :metering_used_metric => :integer,
    :metering_used_cost   => :float
  )

  def self.build_results_for_report_chargeback(options)
    _log.info("Calculating chargeback costs...")
    @options = options = ReportOptions.new_from_h(options)

    data = {}
    rates = RatesCache.new
    ConsumptionHistory.for_report(self, options) do |consumption|
      rates_to_apply = rates.get(consumption)

      key = report_row_key(consumption)
      data[key] ||= new(options, consumption)

      chargeback_rates = data[key]["chargeback_rates"].split(', ') + rates_to_apply.collect(&:description)
      data[key]["chargeback_rates"] = chargeback_rates.uniq.join(', ')

      # we are getting hash with metrics and costs for metrics defined for chargeback
      if Settings[:new_chargeback]
        data[key].new_chargeback_calculate_costs(consumption, rates_to_apply)
      else
        data[key].calculate_costs(consumption, rates_to_apply)
      end
    end
    _log.info("Calculating chargeback costs...Complete")

    [data.values]
  end

  def self.report_row_key(consumption)
    ts_key = @options.start_of_report_step(consumption.timestamp)
    if @options[:groupby_tag].present?
      classification = @options.classification_for(consumption)
      classification_id = classification.present? ? classification.id : 'none'
      "#{classification_id}_#{ts_key}"
    elsif @options[:groupby_label].present?
      "#{groupby_label_value(consumption, @options[:groupby_label])}_#{ts_key}"
    else
      default_key(consumption, ts_key)
    end
  end

  def self.default_key(consumption, ts_key)
    "#{consumption.resource_id}_#{ts_key}"
  end

  def self.groupby_label_value(consumption, groupby_label)
    nil
  end

  def initialize(options, consumption)
    @options = options
    super()
    if @options[:groupby_tag].present?
      classification = @options.classification_for(consumption)
      self.tag_name = classification.present? ? classification.description : _('<Empty>')
    elsif @options[:groupby_label].present?
      label_value = self.class.groupby_label_value(consumption, options[:groupby_label])
      self.label_name = label_value.present? ? label_value : _('<Empty>')
    else
      init_extra_fields(consumption)
    end
    self.start_date, self.end_date, self.display_range = options.report_step_range(consumption.timestamp)
    self.interval_name = options.interval
    self.chargeback_rates = ''
    self.entity ||= consumption.resource
  end

  def showback_category
    case self
    when ChargebackVm
      'Vm'
    when ChargebackContainerProject
      'Container'
    when ChargebackContainerImage
      'ContainerImage'
    end
  end

  def new_chargeback_calculate_costs(consumption, rates)
    self.fixed_compute_metric = consumption.chargeback_fields_present if consumption.chargeback_fields_present

    rates.each do |rate|
      plan = ManageIQ::Consumption::ShowbackPricePlan.find_or_create_by(:description => rate.description,
                                                                        :name        => rate.description,
                                                                        :resource    => MiqEnterprise.first)
      
      data = {}
      rate.rate_details_relevant_to(relevant_fields).each do |r|
        r.populate_showback_rate(plan, r, showback_category)
        measure = r.chargeable_field.showback_measure
        dimension, _, _ = r.chargeable_field.showback_dimension
        value = r.chargeable_field.measure(consumption, @options)
        data[measure] ||= {}
        data[measure][dimension] = [value, r.showback_unit(ChargeableField::UNITS[r.chargeable_field.metric])]
      end
    end
  end

  def calculate_costs(consumption, rates)<commit_msg>Calculate cost with using new chargeback<commit_after>class Chargeback < ActsAsArModel
  set_columns_hash( # Fields common to any chargeback type
    :start_date           => :datetime,
    :end_date             => :datetime,
    :interval_name        => :string,
    :display_range        => :string,
    :chargeback_rates     => :string,
    :entity               => :binary,
    :tag_name             => :string,
    :label_name           => :string,
    :fixed_compute_metric => :integer,
    :metering_used_metric => :integer,
    :metering_used_cost   => :float
  )

  def self.build_results_for_report_chargeback(options)
    _log.info("Calculating chargeback costs...")
    @options = options = ReportOptions.new_from_h(options)

    data = {}
    rates = RatesCache.new
    ConsumptionHistory.for_report(self, options) do |consumption|
      rates_to_apply = rates.get(consumption)

      key = report_row_key(consumption)
      data[key] ||= new(options, consumption)

      chargeback_rates = data[key]["chargeback_rates"].split(', ') + rates_to_apply.collect(&:description)
      data[key]["chargeback_rates"] = chargeback_rates.uniq.join(', ')

      # we are getting hash with metrics and costs for metrics defined for chargeback
      if Settings[:new_chargeback]
        data[key].new_chargeback_calculate_costs(consumption, rates_to_apply)
      else
        data[key].calculate_costs(consumption, rates_to_apply)
      end
    end
    _log.info("Calculating chargeback costs...Complete")

    [data.values]
  end

  def self.report_row_key(consumption)
    ts_key = @options.start_of_report_step(consumption.timestamp)
    if @options[:groupby_tag].present?
      classification = @options.classification_for(consumption)
      classification_id = classification.present? ? classification.id : 'none'
      "#{classification_id}_#{ts_key}"
    elsif @options[:groupby_label].present?
      "#{groupby_label_value(consumption, @options[:groupby_label])}_#{ts_key}"
    else
      default_key(consumption, ts_key)
    end
  end

  def self.default_key(consumption, ts_key)
    "#{consumption.resource_id}_#{ts_key}"
  end

  def self.groupby_label_value(consumption, groupby_label)
    nil
  end

  def initialize(options, consumption)
    @options = options
    super()
    if @options[:groupby_tag].present?
      classification = @options.classification_for(consumption)
      self.tag_name = classification.present? ? classification.description : _('<Empty>')
    elsif @options[:groupby_label].present?
      label_value = self.class.groupby_label_value(consumption, options[:groupby_label])
      self.label_name = label_value.present? ? label_value : _('<Empty>')
    else
      init_extra_fields(consumption)
    end
    self.start_date, self.end_date, self.display_range = options.report_step_range(consumption.timestamp)
    self.interval_name = options.interval
    self.chargeback_rates = ''
    self.entity ||= consumption.resource
  end

  def showback_category
    case self
    when ChargebackVm
      'Vm'
    when ChargebackContainerProject
      'Container'
    when ChargebackContainerImage
      'ContainerImage'
    end
  end

  def new_chargeback_calculate_costs(consumption, rates)
    self.fixed_compute_metric = consumption.chargeback_fields_present if consumption.chargeback_fields_present

    rates.each do |rate|
      plan = ManageIQ::Consumption::ShowbackPricePlan.find_or_create_by(:description => rate.description,
                                                                        :name        => rate.description,
                                                                        :resource    => MiqEnterprise.first)
      
      data = {}
      rate.rate_details_relevant_to(relevant_fields).each do |r|
        r.populate_showback_rate(plan, r, showback_category)
        measure = r.chargeable_field.showback_measure
        dimension, _, _ = r.chargeable_field.showback_dimension
        value = r.chargeable_field.measure(consumption, @options)
        data[measure] ||= {}
        data[measure][dimension] = [value, r.showback_unit(ChargeableField::UNITS[r.chargeable_field.metric])]
      end

      results = plan.calculate_list_of_costs_input(resource_type:  showback_category,
                                                   data:           data,
                                                   start_time:     consumption.instance_variable_get("@start_time"),
                                                   end_time:       consumption.instance_variable_get("@end_time"),
                                                   cycle_duration: @options.duration_of_report_step)
    end
  end

  def calculate_costs(consumption, rates)
{'fraction_non_alphanumeric': 0.09669811320754718, 'fraction_numerical': 0.0, 'mean_word_length': 2.865017361111111, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4192744', 'n_tokens_mistral': 2609, 'n_tokens_neox': 2539, 'n_words': 435}