diff --git a/app/models/reporting_event_rollup.rb b/app/models/reporting_event_rollup.rb new file mode 100644 index 000000000..8be45cedd --- /dev/null +++ b/app/models/reporting_event_rollup.rb @@ -0,0 +1,48 @@ +# == Schema Information +# +# Table name: reporting_events_rollups +# +# id :bigint not null, primary key +# count :bigint default(0), not null +# date :date not null +# dimension_id :bigint not null +# dimension_type :string not null +# metric :string not null +# sum_value :float default(0.0), not null +# sum_value_business_hours :float default(0.0), not null +# created_at :datetime not null +# updated_at :datetime not null +# account_id :integer not null +# +# Indexes +# +# index_rollup_summary (account_id,dimension_type,date) +# index_rollup_timeseries (account_id,metric,date) +# index_rollup_unique_key (account_id,date,dimension_type,dimension_id,metric) UNIQUE +# + +class ReportingEventRollup < ApplicationRecord + belongs_to :account + + # Store string values directly in the database for better readability and debugging + enum :dimension_type, %w[account agent inbox team].index_by(&:itself) + enum :metric, %w[ + resolutions_count + first_response + resolution_time + reply_time + bot_resolutions_count + bot_handoffs_count + ].index_by(&:itself) + + validates :account_id, presence: true + validates :date, presence: true + validates :dimension_type, presence: true + validates :dimension_id, presence: true + validates :metric, presence: true + validates :count, numericality: { greater_than_or_equal_to: 0 } + + scope :for_date_range, ->(start_date, end_date) { where(date: start_date..end_date) } + scope :for_dimension, ->(type, id) { where(dimension_type: type, dimension_id: id) } + scope :for_metric, ->(metric) { where(metric: metric) } +end diff --git a/db/migrate/20260211145813_create_reporting_events_rollup.rb b/db/migrate/20260211145813_create_reporting_events_rollup.rb new file mode 100644 index 000000000..411469eb7 --- /dev/null +++ b/db/migrate/20260211145813_create_reporting_events_rollup.rb @@ -0,0 +1,34 @@ +class CreateReportingEventsRollup < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + create_table :reporting_events_rollups do |t| + t.integer :account_id, null: false + t.date :date, null: false + t.string :dimension_type, null: false + t.bigint :dimension_id, null: false + t.string :metric, null: false + t.bigint :count, default: 0, null: false + t.float :sum_value, default: 0.0, null: false + t.float :sum_value_business_hours, default: 0.0, null: false + + t.timestamps + end + + # Unique index for upsert conflict resolution + add_index :reporting_events_rollups, + [:account_id, :date, :dimension_type, :dimension_id, :metric], + unique: true, + name: 'index_rollup_unique_key' + + # Query index for timeseries (date range scans) + add_index :reporting_events_rollups, + [:account_id, :metric, :date], + name: 'index_rollup_timeseries' + + # Query index for summaries (dimension scans) + add_index :reporting_events_rollups, + [:account_id, :dimension_type, :date], + name: 'index_rollup_summary' + end +end