diff --git a/app/models/daily_usage.rb b/app/models/daily_usage.rb index 7682e531537..a6c8e2b8309 100644 --- a/app/models/daily_usage.rb +++ b/app/models/daily_usage.rb @@ -5,12 +5,12 @@ class DailyUsage < ApplicationRecord belongs_to :customer belongs_to :subscription - scope :refreshed_at_in_timezone, ->(timestamp) do + scope :usage_date_in_timezone, ->(timestamp) do at_time_zone = Utils::Timezone.at_time_zone_sql(customer: "cus", organization: "org") joins("INNER JOIN customers AS cus ON daily_usages.customer_id = cus.id") .joins("INNER JOIN organizations AS org ON daily_usages.organization_id = org.id") - .where("DATE((daily_usages.refreshed_at)#{at_time_zone}) = DATE(:timestamp#{at_time_zone})", timestamp:) + .where("DATE((daily_usages.usage_date)#{at_time_zone}) = DATE(:timestamp#{at_time_zone})", timestamp:) end end diff --git a/app/services/daily_usages/compute_all_service.rb b/app/services/daily_usages/compute_all_service.rb index d3f4ca66228..dee7d5c18d5 100644 --- a/app/services/daily_usages/compute_all_service.rb +++ b/app/services/daily_usages/compute_all_service.rb @@ -24,17 +24,17 @@ def subscriptions # NOTE(DailyUsage): For now the query filters organizations having revenue_analytics premium integrations # This might change in the future Subscription - .with(already_refreshed_today: already_refreshed_today) + .with(existing_daily_usage:) .joins(customer: :organization) .merge(Organization.with_revenue_analytics_support) - .joins("LEFT JOIN already_refreshed_today ON subscriptions.id = already_refreshed_today.subscription_id") + .joins("LEFT JOIN existing_daily_usage ON subscriptions.id = existing_daily_usage.subscription_id") .active - .where("already_refreshed_today.subscription_id IS NULL") # Exclude subscriptions that already have a daily usage record for today in customer's timezone - .where("DATE_PART('hour', (:timestamp#{at_time_zone})) IN (0, 1, 2)", timestamp:) # Refresh the usage as soom as a subscription starts a new day in customer's timezone + .where("existing_daily_usage.subscription_id IS NULL") # Exclude subscriptions that already have a daily usage record for yesterday in customer's timezone + .where("DATE_PART('hour', (:timestamp#{at_time_zone})) IN (0, 1, 2)", timestamp:) # Store the usage as soon as a subscription starts a new day in customer's timezone end - def already_refreshed_today - DailyUsage.refreshed_at_in_timezone(timestamp).select(:subscription_id) + def existing_daily_usage + DailyUsage.usage_date_in_timezone(timestamp.to_date - 1.day).select(:subscription_id) end end end diff --git a/app/services/daily_usages/compute_diff_service.rb b/app/services/daily_usages/compute_diff_service.rb index a2d58bff2fd..7c486b972ff 100644 --- a/app/services/daily_usages/compute_diff_service.rb +++ b/app/services/daily_usages/compute_diff_service.rb @@ -58,14 +58,12 @@ def call attr_reader :daily_usage - delegate :subscription, :refreshed_at, :from_datetime, :to_datetime, to: :daily_usage + delegate :subscription, :usage_date, :from_datetime, :to_datetime, to: :daily_usage def previous_daily_usage - @previous_daily_usage ||= DailyUsage - .where(subscription_id: subscription.id, from_datetime:, to_datetime:) - .where("refreshed_at < ?", refreshed_at) - .order(refreshed_at: :desc) - .first + @previous_daily_usage ||= subscription.daily_usages + .where(from_datetime:, to_datetime:) + .find_by(usage_date: usage_date - 1.day) end def apply_diff(previous_values, current_values) diff --git a/app/services/daily_usages/compute_service.rb b/app/services/daily_usages/compute_service.rb index 0b55a99762d..f726599586a 100644 --- a/app/services/daily_usages/compute_service.rb +++ b/app/services/daily_usages/compute_service.rb @@ -10,7 +10,7 @@ def initialize(subscription:, timestamp:) def call if subscription_billing_day? - # Usage on billing day will be computed using the periodic invoice as we cannont rely on the caching mechanism + # Usage on billing day will be computed using the periodic invoice as we cannot rely on the caching mechanism return result end @@ -28,7 +28,7 @@ def call from_datetime: current_usage.from_datetime, to_datetime: current_usage.to_datetime, refreshed_at: timestamp, - usage_date: date_in_timezone - 1.day + usage_date: ) daily_usage.usage_diff = diff_usage(daily_usage) @@ -65,7 +65,7 @@ def current_usage end def existing_daily_usage - @existing_daily_usage ||= DailyUsage.refreshed_at_in_timezone(timestamp) + @existing_daily_usage ||= DailyUsage.usage_date_in_timezone(usage_date) .find_by(subscription_id: subscription.id) end @@ -86,5 +86,9 @@ def subscription_billing_day? def date_in_timezone @date_in_timezone ||= timestamp.in_time_zone(customer.applicable_timezone).to_date end + + def usage_date + @usage_date ||= date_in_timezone - 1.day + end end end diff --git a/app/services/daily_usages/fill_from_invoice_service.rb b/app/services/daily_usages/fill_from_invoice_service.rb index 9310a8194c1..24d892f251a 100644 --- a/app/services/daily_usages/fill_from_invoice_service.rb +++ b/app/services/daily_usages/fill_from_invoice_service.rb @@ -28,7 +28,7 @@ def call from_datetime: invoice_subscription.from_datetime, to_datetime: invoice_subscription.to_datetime, refreshed_at: invoice_subscription.timestamp, - usage_date: invoice_subscription.charges_to_datetime + usage_date: invoice_subscription.charges_to_datetime.to_date ) daily_usage.usage_diff = diff_usage(daily_usage) @@ -67,7 +67,7 @@ def existing_daily_usage(invoice_subscription) DailyUsage.find_by( from_datetime: invoice_subscription.from_datetime, to_datetime: invoice_subscription.to_datetime, - refreshed_at: invoice_subscription.timestamp, + usage_date: invoice_subscription.charges_to_datetime.to_date, subscription_id: invoice_subscription.subscription_id ) end diff --git a/app/services/daily_usages/fill_history_service.rb b/app/services/daily_usages/fill_history_service.rb index c2b7e14b246..c4075cfe02b 100644 --- a/app/services/daily_usages/fill_history_service.rb +++ b/app/services/daily_usages/fill_history_service.rb @@ -18,8 +18,7 @@ def call datetime = date.in_time_zone(subscription.customer.applicable_timezone).beginning_of_day.utc next if date == Time.zone.today || - subscription.daily_usages.where(usage_date: datetime.to_date - 1.day).exists? || - DailyUsage.refreshed_at_in_timezone(datetime).where(subscription_id: subscription.id).exists? + subscription.daily_usages.where(usage_date: datetime.to_date - 1.day).exists? Timecop.thread_safe = true Timecop.freeze(datetime + 5.minutes) do diff --git a/spec/factories/daily_usages.rb b/spec/factories/daily_usages.rb index 6f245dc82d3..ee7c36454c0 100644 --- a/spec/factories/daily_usages.rb +++ b/spec/factories/daily_usages.rb @@ -11,5 +11,6 @@ to_datetime { Time.current.end_of_month } refreshed_at { Time.current } usage { {} } + usage_date { Date.yesterday } end end diff --git a/spec/models/daily_usage_spec.rb b/spec/models/daily_usage_spec.rb index 10849e8f30b..2cba9da19de 100644 --- a/spec/models/daily_usage_spec.rb +++ b/spec/models/daily_usage_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require "rails_helper" RSpec.describe DailyUsage, type: :model do it { is_expected.to belong_to(:organization) } diff --git a/spec/services/daily_usages/compute_all_service_spec.rb b/spec/services/daily_usages/compute_all_service_spec.rb index 6fdb0b52529..c3825364f9d 100644 --- a/spec/services/daily_usages/compute_all_service_spec.rb +++ b/spec/services/daily_usages/compute_all_service_spec.rb @@ -24,7 +24,7 @@ end context "when subscription usage was already computed" do - before { create(:daily_usage, subscription:, refreshed_at: timestamp + 2.minutes) } + before { create(:daily_usage, subscription:, usage_date: timestamp.to_date - 1.day) } it "does not enqueue any job" do expect(compute_service.call).to be_success diff --git a/spec/services/daily_usages/compute_diff_service_spec.rb b/spec/services/daily_usages/compute_diff_service_spec.rb index 477d9b0e36b..9e5d5f1beae 100644 --- a/spec/services/daily_usages/compute_diff_service_spec.rb +++ b/spec/services/daily_usages/compute_diff_service_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require "rails_helper" RSpec.describe DailyUsages::ComputeDiffService, type: :service do subject(:diff_service) { described_class.new(daily_usage:, previous_daily_usage:) } @@ -167,7 +167,7 @@ } end - it 'computes the diff between the two daily usages' do + it "computes the diff between the two daily usages" do result = diff_service.call expect(result).to be_success @@ -269,10 +269,10 @@ ) end - context 'when the previous daily usage is nil' do + context "when the previous daily usage is nil" do let(:previous_daily_usage) { nil } - it 'returns the current usage as diff' do + it "returns the current usage as diff" do result = diff_service.call expect(result).to be_success diff --git a/spec/services/daily_usages/compute_service_spec.rb b/spec/services/daily_usages/compute_service_spec.rb index 128d65fd3df..15f6a6ee34a 100644 --- a/spec/services/daily_usages/compute_service_spec.rb +++ b/spec/services/daily_usages/compute_service_spec.rb @@ -13,9 +13,10 @@ end let(:timestamp) { Time.zone.parse("2024-10-22 00:05:00") } + let(:usage_date) { Date.parse("2024-10-21") } describe "#call" do - it "creates a daily usage", aggregate_failures: true do + it "creates a daily usage" do travel_to(timestamp) do expect { compute_service.call }.to change(DailyUsage, :count).by(1) @@ -37,12 +38,12 @@ context "when a daily usage already exists" do let(:existing_daily_usage) do - create(:daily_usage, subscription:, organization:, customer:, refreshed_at: timestamp) + create(:daily_usage, subscription:, organization:, customer:, usage_date:) end before { existing_daily_usage } - it "returns the existing daily usage", aggregate_failure: true do + it "returns the existing daily usage" do result = compute_service.call expect(result).to be_success @@ -53,7 +54,7 @@ let(:organization) { create(:organization, timezone: "America/Sao_Paulo") } let(:existing_daily_usage) do - create(:daily_usage, subscription:, organization:, customer:, refreshed_at: timestamp - 4.hours) + create(:daily_usage, subscription:, organization:, customer:, usage_date: usage_date - 4.hours) end it "takes the timezone into account" do @@ -68,7 +69,7 @@ let(:customer) { create(:customer, organization:, timezone: "America/Sao_Paulo") } let(:existing_daily_usage) do - create(:daily_usage, subscription:, organization:, customer:, refreshed_at: timestamp - 4.hours) + create(:daily_usage, subscription:, organization:, customer:, usage_date: usage_date - 4.hours) end it "takes the timezone into account" do @@ -99,7 +100,7 @@ let(:timestamp) { subscription.terminated_at - 1.day } - it "creates a daily usage", aggregate_failures: true do + it "creates a daily usage" do result = compute_service.call expect(result).to be_success