Files
chatwoot/app/services/reports/data_source.rb
T

107 lines
3.0 KiB
Ruby

class Reports::DataSource
SUPPORTED_ROLLUP_DIMENSIONS = %w[account agent inbox].freeze
attr_reader :account, :metric, :dimension_type, :dimension_id,
:scope, :range, :group_by, :timezone,
:timezone_offset, :business_hours
class << self
def for(**context)
adapter_class_for(**context).new(**context)
end
def rollup_eligible?(**context)
account = context[:account]
rollup_enabled_for_account?(account) &&
!hourly_grouping?(context[:group_by]) &&
supported_dimension?(context[:dimension_type]) &&
timezone_matches_account?(account, context[:timezone], context[:timezone_offset]) &&
supported_metric?(context[:metric])
end
def timezone_matches_account?(account, timezone, timezone_offset)
return normalized_timezone_identifier(timezone) == normalized_timezone_identifier(account.reporting_timezone) if timezone.present?
return false if timezone_offset.blank?
offset_in_seconds = timezone_offset.to_f * 3600
account_zone = ActiveSupport::TimeZone[account.reporting_timezone]
account_zone&.now&.utc_offset == offset_in_seconds
end
private
def adapter_class_for(**context)
rollup_eligible?(**context) ? Reports::RollupDataSource : Reports::RawDataSource
end
def rollup_enabled_for_account?(account)
account.reporting_timezone.present? && account.feature_enabled?('reporting_events_rollup')
end
def hourly_grouping?(group_by)
group_by.to_s == 'hour'
end
def supported_dimension?(dimension_type)
SUPPORTED_ROLLUP_DIMENSIONS.include?((dimension_type.presence || 'account').to_s)
end
def supported_metric?(metric)
metric.blank? || ReportingEvents::MetricRegistry.rollup_supported_metric?(metric)
end
def normalized_timezone_identifier(timezone)
ActiveSupport::TimeZone[timezone]&.tzinfo&.name
end
end
def initialize(**context)
@account = context[:account]
@metric = context[:metric]
@dimension_type = (context[:dimension_type].presence || 'account').to_s
@dimension_id = context[:dimension_id]
@scope = context[:scope]
@range = context[:range]
@group_by = context[:group_by].to_s.presence || 'day'
@timezone = context[:timezone]
@timezone_offset = context[:timezone_offset]
@business_hours = context[:business_hours]
end
private
def report_metric
@report_metric ||= ReportingEvents::MetricRegistry.report_metric(metric)
end
def average_metric?
report_metric&.dig(:aggregate) == :average
end
def count_metric?
!average_metric?
end
def rollup_metric
report_metric&.dig(:rollup_metric)
end
def raw_event_name
report_metric&.dig(:raw_event_name)
end
def raw_count_strategy
report_metric&.dig(:raw_count_strategy)
end
def summary_metrics
@summary_metrics ||= ReportingEvents::MetricRegistry.summary_metrics
end
def use_business_hours?
ActiveModel::Type::Boolean.new.cast(business_hours)
end
end