module PIM::Statistics

Constants

VALIDATION_KEY_ATTRIBUTE_TRANSFORMER

Transform validation key to attribute

Public Class Methods

calculate(&block) click to toggle source

Deprecated! Used for legacy statistics only! Please convert to ‘calculate_statistics’!

# File statistics.rb, line 410
def self.calculate &block

  # Create statistics manager without user statistics
  manager = create_statistics_manager

  # Calculate statistics
  result = manager.calculate_statistics $oldItem, $item

  # Create and calculate old user statistics
  old_result = OldStatisticsResult.new
  block.call $oldItem, $item, old_result
  result += old_result.as_json

  PIM.return_json(result)

end
calculate_statistics(&block) click to toggle source

Method to be called in data model specific statistics

# File statistics.rb, line 397
def self.calculate_statistics &block

  # Create statistics manager
  manager = create_statistics_manager features: $statistic_features, &block

  # Calculate statistics
  result = manager.calculate_statistics $oldItem, $item

  PIM.return_json(result)

end
create_statistics_manager(features: nil, &block) click to toggle source
# File statistics.rb, line 427
def self.create_statistics_manager features: nil, &block

  # Create new statistics manager
  manager = StatisticsManager.new features: features

  # Create system statistics
  manager.create_statistics do

    # When 'scopes' is true, apply the calculation to each scope of the item
    statistic_with_template '__categories_statistic', scopes: true do

      dimension_keys = get_array_param(params, :dimensions)

      # New: Apply calculations to either 'new_item' or 'old_item' by iterating over 'items'!
      items.each do |item, incr_value|

        dimension_values = get_item_values(item, dimension_keys)

        # Note: With 'scopes: true' every 'incr', 'decr' or 'set' will add the statistic value to EVERY scope of the item!
        category = item['category__']
        incr(category, *dimension_values, incr_value: incr_value)

      end

    end

    # When 'scopes' is true, apply the calculation to each scope of the item
    statistic_with_template '__compliance_statistic', scopes: true do

      dimension_keys = get_array_param(params, :dimensions)

      # A 'scope_block' is needed to filter each entry by: scope, key, *dimensions
      # In this case, we want to:
      # - transform a 'validation' key to an attribute (VALIDATION_KEY_ATTRIBUTE_TRANSFORMER)
      # - check the datamodel if the attribute is included for the specified scope
      scope_block = create_scope_block_for_item_scope_attribute_filter(&VALIDATION_KEY_ATTRIBUTE_TRANSFORMER)

      # New: Apply calculations to either 'new_item' or 'old_item' by iterating over 'items'!
      items.each do |item, incr_value|

        dimension_values = get_item_values(item, dimension_keys)

        # Count 'compliance' per scope by first filtering the validation-errors
        scopes.each do |scope|

          compliance = case
            when item['validation_dirty__'] then 'dirty'
            else
              validation_errors = (item['validation__'] || []).filter { |key| scope_block.call(scope, key, *dimension_values) }
              is_empty?(validation_errors) ? 'compliant' : 'non_compliant'
          end

          incr(compliance, *dimension_values, incr_value: incr_value, scopes: [scope])

        end

        # Count 'total' for all scopes
        incr('total', *dimension_values, incr_value: incr_value)

        # Count 'published' only for 'nil' scope
        if item['published__']
          incr('published', *dimension_values, incr_value: incr_value) do |scope|
            scope.nil?
          end
        end

      end

    end

    statistic_with_template '__validation_overview', '__validation_errors_statistic', scopes: true do

      dimension_keys = get_array_param(params, :dimensions)

      # A 'scope_block' is needed to filter each entry by: scope, key, *dimensions
      # In this case, we want to:
      # - transform a 'validation' key to an attribute (VALIDATION_KEY_ATTRIBUTE_TRANSFORMER)
      # - check the datamodel if the attribute is included for the specified scope
      scope_block = create_scope_block_for_item_scope_attribute_filter(&VALIDATION_KEY_ATTRIBUTE_TRANSFORMER)

      # New: Apply calculations to either 'new_item' or 'old_item' by iterating over 'items'!
      items.each do |item, incr_value|

        dimension_values = get_item_values(item, dimension_keys)

        # Filter validation errors based on scope
        validations = item['validation__'] || []
        incr_all(validations, *dimension_values, incr_value: incr_value, &scope_block)

      end

    end

    statistic_with_template '__validation_warnings', '__validation_warnings_statistic', scopes: true do

      dimension_keys = get_array_param(params, :dimensions)

      # A 'scope_block' is needed to filter each entry by: scope, key, *dimensions
      # In this case, we want to:
      # - transform a 'validation' key to an attribute (VALIDATION_KEY_ATTRIBUTE_TRANSFORMER)
      # - check the datamodel if the attribute is included for the specified scope
      scope_block = create_scope_block_for_item_scope_attribute_filter(&VALIDATION_KEY_ATTRIBUTE_TRANSFORMER)

      # New: Apply calculations to either 'new_item' or 'old_item' by iterating over 'items'!
      items.each do |item, incr_value|

        dimension_values = get_item_values(item, dimension_keys)

        # Filter validation warnings based on scope
        validations = item['validation_warnings__'] || []
        incr_all(validations, *dimension_values, incr_value: incr_value, &scope_block)

      end

    end

    statistic_with_template '__published_to', '__published_to_statistic' do

      dimension_keys = get_array_param(params, :dimensions)

      # New: Apply calculations to either 'new_item' or 'old_item' by iterating over 'items'!
      items.each do |item, incr_value|

        publications = item['publications__']
        next if is_empty?(publications)

        dimension_values = get_item_values(item, dimension_keys)
        incr_all(publications, *dimension_values, incr_value: incr_value)

      end

    end

    statistic_with_template '__publications_active_statistic' do

      dimension_keys = get_array_param(params, :dimensions)

      if old_item
        publications_active = old_item['publications_active__'] || []
        if not publications_active.empty?
          dimension_values = get_item_values(old_item, dimension_keys)
          decr_all(publications_active, *dimension_values)
        end
      end
      if new_item
        publications_active = new_item['publications_active__'] || []
        if not publications_active.empty?
          dimension_values = get_item_values(new_item, dimension_keys)
          incr_all(publications_active, *dimension_values)
        end
      end

    end

    statistic_with_template '__publications_dirty_statistic' do

      dimension_keys = get_array_param(params, :dimensions)

      if old_item
        publications_dirty = old_item['publications_dirty__'] || []
        if not publications_dirty.empty?
          dimension_values = get_item_values(old_item, dimension_keys)
          decr_all(publications_dirty, *dimension_values)
        end
      end
      if new_item
        publications_dirty = new_item['publications_dirty__'] || []
        if not publications_dirty.empty?
          dimension_values = get_item_values(new_item, dimension_keys)
          incr_all(publications_dirty, *dimension_values)
        end
      end

    end

    statistic_with_template '__publications_statistic' do

      # Note that 'target' can be channelId:subDestination (or channelId or organizationId),
      # it is not possible to add any other dimension, because these are added using ':'!
      # The only way to fix it, is to either 'swap' key and dimension or replace the ':'
      # in our target.

      if old_item

        published = old_item['publications__'] || []
        published.each do |target|
          decr('published', target)
        end

        publications_active = old_item['publications_active__'] || []
        publications_active.each do |target|
          decr('active', target)
        end

        publications_dirty = old_item['publications_dirty__'] || []
        publications_dirty.each do |target|
          decr('dirty', target)
        end

      end
      if new_item

        published = new_item['publications__'] || []
        published.each do |target|
          incr('published', target)
        end

        publications_active = new_item['publications_active__'] || []
        publications_active.each do |target|
          incr('active', target)
        end

        publications_dirty = new_item['publications_dirty__'] || []
        publications_dirty.each do |target|
          incr('dirty', target)
        end

      end

    end

    statistic_with_template '__received_from', '__received_from_statistic' do

      dimension_keys = get_array_param(params, :dimensions)

      if old_item
        supplier = old_item['supplier__']
        if not PIM.is_empty?(supplier)
          dimension_values = get_item_values(old_item, dimension_keys)
          decr(supplier, *dimension_values)
        end
      end
      if new_item
        supplier = new_item['supplier__']
        if not PIM.is_empty?(supplier)
          dimension_values = get_item_values(new_item, dimension_keys)
          incr(supplier, *dimension_values)
        end
      end

    end

    statistic_with_template '__review_errors', '__review_errors_statistic' do

      dimension_keys = get_array_param(params, :dimensions)

      if old_item
        validations = old_item['reviewErrors__'] || []
        validations = validations.map do |validation|
          validation = validation.split(':', 4)[-1]
        end
        dimension_values = get_item_values(old_item, dimension_keys)
        decr_all(validations, *dimension_values)
      end
      if new_item
        validations = new_item['reviewErrors__'] || []
        validations = validations.map do |validation|
          validation = validation.split(':', 4)[-1]
        end
        dimension_values = get_item_values(new_item, dimension_keys)
        incr_all(validations, *dimension_values)
      end

    end

    statistic_with_template '__review_warnings', '__review_warnings_statistic' do

      dimension_keys = get_array_param(params, :dimensions)

      if old_item
        validations = old_item['reviewWarnings__'] || []
        validations = validations.map do |validation|
          validation = validation.split(':', 4)[-1]
        end
        dimension_values = get_item_values(old_item, dimension_keys)
        decr_all(validations, *dimension_values)
      end
      if new_item
        validations = new_item['reviewWarnings__'] || []
        validations = validations.map do |validation|
          validation = validation.split(':', 4)[-1]
        end
        dimension_values = get_item_values(new_item, dimension_keys)
        incr_all(validations, *dimension_values)
      end

    end

    statistic_with_template '__review_statistic' do

      if old_item

        # Add statistic by publication
        publications = old_item['publications__'] || []
        publications.each do |publication|
          decr('total_published', publication) # channelId:subDestination OR channelId OR organizationId
        end

        # Add statistics by review status
        reviews = old_item['reviews__'] || []
        reviews.each do |review|
          type, reviewer, sub_destination, review_status = review.split(':')
            reviewer = "#{reviewer}:#{sub_destination}" unless sub_destination.nil? or sub_destination.empty?
            decr(review_status, reviewer) # reviewer = channelId:subDestination OR channelId
            decr('total_reviews', reviewer)
        end

      end

      if new_item

        # Add statistic by publication
        publications = new_item['publications__'] || []
        publications.each do |publication|
          incr('total_published', publication) # channelId:subDestination OR channelId OR organizationId
        end

        # Add statistics by review status
        reviews = new_item['reviews__'] || []
        reviews.each do |review|
          type, reviewer, sub_destination, review_status = review.split(':')
            reviewer = "#{reviewer}:#{sub_destination}" unless sub_destination.nil? or sub_destination.empty?
            incr(review_status, reviewer) # reviewer = channelId:subDestination OR channelId
            incr('total_reviews', reviewer)
        end

      end

    end

  end

  # Create user statistics, if specified
  manager.create_statistics &block if block

  manager

end