diff --git a/app/models/billable_metric.rb b/app/models/billable_metric.rb index 5e78c215611..639cecbfb1d 100644 --- a/app/models/billable_metric.rb +++ b/app/models/billable_metric.rb @@ -13,7 +13,7 @@ class BillableMetric < ApplicationRecord has_many :coupon_targets has_many :coupons, through: :coupon_targets has_many :groups, dependent: :delete_all - has_many :filters, -> { order(:key) }, dependent: :delete_all, class_name: 'BillableMetricFilter' + has_many :filters, -> { order(:key) }, dependent: :delete_all, class_name: "BillableMetricFilter" AGGREGATION_TYPES = { count_agg: 0, @@ -27,9 +27,12 @@ class BillableMetric < ApplicationRecord }.freeze AGGREGATION_TYPES_PAYABLE_IN_ADVANCE = %i[count_agg sum_agg unique_count_agg custom_agg].freeze - WEIGHTED_INTERVAL = {seconds: 'seconds'}.freeze + ROUNDING_FUNCTIONS = {round: "round", ceil: "ceil", floor: "floor"}.freeze + + WEIGHTED_INTERVAL = {seconds: "seconds"}.freeze enum aggregation_type: AGGREGATION_TYPES + enum rounding_function: ROUNDING_FUNCTIONS enum weighted_interval: WEIGHTED_INTERVAL validate :validate_recurring @@ -45,6 +48,7 @@ class BillableMetric < ApplicationRecord inclusion: {in: WEIGHTED_INTERVAL.values}, if: :weighted_sum_agg? validates :custom_aggregator, presence: true, if: :custom_agg? + validates :rounding_function, inclusion: {in: ROUNDING_FUNCTIONS.values}, allow_nil: true default_scope -> { kept } @@ -91,21 +95,23 @@ def validate_expression # # Table name: billable_metrics # -# id :uuid not null, primary key -# aggregation_type :integer not null -# code :string not null -# custom_aggregator :text -# deleted_at :datetime -# description :string -# expression :string -# field_name :string -# name :string not null -# properties :jsonb -# recurring :boolean default(FALSE), not null -# weighted_interval :enum -# created_at :datetime not null -# updated_at :datetime not null -# organization_id :uuid not null +# id :uuid not null, primary key +# aggregation_type :integer not null +# code :string not null +# custom_aggregator :text +# deleted_at :datetime +# description :string +# expression :string +# field_name :string +# name :string not null +# properties :jsonb +# recurring :boolean default(FALSE), not null +# rounding_function :enum +# rounding_precision :integer +# weighted_interval :enum +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :uuid not null # # Indexes # diff --git a/db/migrate/20240314165306_migrate_groups_to_filters.rb b/db/migrate/20240314165306_migrate_groups_to_filters.rb index f5b0a45a4e2..2f55e84f6bc 100644 --- a/db/migrate/20240314165306_migrate_groups_to_filters.rb +++ b/db/migrate/20240314165306_migrate_groups_to_filters.rb @@ -3,6 +3,11 @@ class MigrateGroupsToFilters < ActiveRecord::Migration[7.0] disable_ddl_transaction! + class BillableMetric < ApplicationRecord + has_many :groups + has_many :filters, -> { order(:key) }, dependent: :delete_all, class_name: 'BillableMetricFilter' + end + class BillableMetricFilter < ApplicationRecord belongs_to :billable_metric end @@ -26,11 +31,6 @@ class Charge < ApplicationRecord has_many :filter_values, through: :filters, class_name: 'ChargeFilterValue', source: :values end - class BillableMetric < ApplicationRecord - has_many :groups - has_many :filters, -> { order(:key) }, dependent: :delete_all, class_name: 'BillableMetricFilter' - end - class ChargeFilter < ApplicationRecord belongs_to :charge has_many :values, class_name: 'ChargeFilterValue', dependent: :destroy diff --git a/db/migrate/20240603095841_refresh_cached_aggregations.rb b/db/migrate/20240603095841_refresh_cached_aggregations.rb index 8cae809e92e..2642e02cc33 100644 --- a/db/migrate/20240603095841_refresh_cached_aggregations.rb +++ b/db/migrate/20240603095841_refresh_cached_aggregations.rb @@ -1,6 +1,18 @@ # frozen_string_literal: true class RefreshCachedAggregations < ActiveRecord::Migration[7.0] + class BillableMetric < ApplicationRecord + enum aggregation_type: { + count_agg: 0, + sum_agg: 1, + max_agg: 2, + unique_count_agg: 3, + weighted_sum_agg: 5, + latest_agg: 6, + custom_agg: 7 + } + end + class Subscription < ApplicationRecord belongs_to :plan end diff --git a/db/migrate/20241029141351_add_rounding_options_to_billable_metrics.rb b/db/migrate/20241029141351_add_rounding_options_to_billable_metrics.rb new file mode 100644 index 00000000000..2de9a7a65be --- /dev/null +++ b/db/migrate/20241029141351_add_rounding_options_to_billable_metrics.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class AddRoundingOptionsToBillableMetrics < ActiveRecord::Migration[7.1] + def change + create_enum :billable_metric_rounding_function, %w[round floor ceil] + + safety_assured do + change_table :billable_metrics, bulk: true do |t| + t.enum :rounding_function, enum_type: "billable_metric_rounding_function" + t.integer :rounding_precision + end + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 56d5ec6ffd0..e8dcab53806 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -18,6 +18,7 @@ # Custom types defined in this database. # Note that some types may not work with other database engines. Be careful if changing database. + create_enum "billable_metric_rounding_function", ["round", "floor", "ceil"] create_enum "billable_metric_weighted_interval", ["seconds"] create_enum "customer_type", ["company", "individual"] create_enum "subscription_invoicing_reason", ["subscription_starting", "subscription_periodic", "subscription_terminating", "in_advance_charge", "in_advance_charge_periodic", "progressive_billing"] @@ -177,6 +178,8 @@ t.enum "weighted_interval", enum_type: "billable_metric_weighted_interval" t.text "custom_aggregator" t.string "expression" + t.enum "rounding_function", enum_type: "billable_metric_rounding_function" + t.integer "rounding_precision" t.index ["deleted_at"], name: "index_billable_metrics_on_deleted_at" t.index ["organization_id", "code", "expression"], name: "index_billable_metrics_on_org_id_and_code_and_expr", where: "((expression IS NOT NULL) AND ((expression)::text <> ''::text))" t.index ["organization_id", "code"], name: "index_billable_metrics_on_organization_id_and_code", unique: true, where: "(deleted_at IS NULL)"