107 lines
3.0 KiB
Ruby
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
|