From 950bb1f2b097677972eac1014edb752b9d1bbbd2 Mon Sep 17 00:00:00 2001 From: Vincent Pochet Date: Fri, 25 Oct 2024 11:17:59 +0200 Subject: [PATCH] Use refreshed_at for identifying existing DailyUsage --- .../daily_usages/compute_all_service.rb | 4 +- app/services/daily_usages/compute_service.rb | 7 ++-- ...5081408_add_refreshed_at_to_daily_usage.rb | 2 +- spec/factories/daily_usages.rb | 1 + spec/factories/subscriptions.rb | 4 ++ .../daily_usages/compute_all_service_spec.rb | 2 +- .../daily_usages/compute_service_spec.rb | 42 +++++++++++++++++-- 7 files changed, 51 insertions(+), 11 deletions(-) diff --git a/app/services/daily_usages/compute_all_service.rb b/app/services/daily_usages/compute_all_service.rb index c0352691ca34..8d46f0bec0b4 100644 --- a/app/services/daily_usages/compute_all_service.rb +++ b/app/services/daily_usages/compute_all_service.rb @@ -23,7 +23,7 @@ def call attr_reader :timestamp def subscriptions - # TODO: Filter subscriptions based on the feature availability at organization level + # TODO(DailyUsage): Filter subscriptions based on the feature availability at organization level - Not Decided Yet Subscription .with(already_refreshed_today: already_refreshed_today) .joins(customer: :organization) @@ -36,7 +36,7 @@ def subscriptions def already_refreshed_today where_clause = <<-SQL DATE( - (daily_usages.created_at)#{at_time_zone(customer: "cus", organization: "org")} + (daily_usages.refreshed_at)#{at_time_zone(customer: "cus", organization: "org")} ) = DATE(:timestamp#{at_time_zone(customer: "cus", organization: "org")}) SQL diff --git a/app/services/daily_usages/compute_service.rb b/app/services/daily_usages/compute_service.rb index 3a584f26bef3..7afd5aa8a42b 100644 --- a/app/services/daily_usages/compute_service.rb +++ b/app/services/daily_usages/compute_service.rb @@ -19,9 +19,10 @@ def call customer: subscription.customer, subscription:, external_subscription_id: subscription.external_id, - usage: ::V1::Customers::UsageSerializer.new(current_usage).serialize.to_json, + usage: ::V1::Customers::UsageSerializer.new(current_usage).serialize, from_datetime: current_usage.from_datetime, - to_datetime: current_usage.to_datetime # TODO: persist the timestamp + to_datetime: current_usage.to_datetime, + refreshed_at: timestamp ) result.daily_usage = daily_usage @@ -44,7 +45,7 @@ def existing_daily_usage @existing_daily_usage ||= DailyUsage .joins(customer: :organization) .where(subscription_id: subscription.id) - .where("DATE((daily_usages.created_at)#{at_time_zone}) = DATE(:timestamp#{at_time_zone})", timestamp:) + .where("DATE((daily_usages.refreshed_at)#{at_time_zone}) = DATE(:timestamp#{at_time_zone})", timestamp:) .first end end diff --git a/db/migrate/20241025081408_add_refreshed_at_to_daily_usage.rb b/db/migrate/20241025081408_add_refreshed_at_to_daily_usage.rb index e488ebc069dd..b69f13707395 100644 --- a/db/migrate/20241025081408_add_refreshed_at_to_daily_usage.rb +++ b/db/migrate/20241025081408_add_refreshed_at_to_daily_usage.rb @@ -3,7 +3,7 @@ class AddRefreshedAtToDailyUsage < ActiveRecord::Migration[7.1] def change safety_assured do - add_column :daily_usages, :refreshed_at, :datetime, null: false + add_column :daily_usages, :refreshed_at, :datetime, null: false # rubocop:disable Rails/NotNullColumn end end end diff --git a/spec/factories/daily_usages.rb b/spec/factories/daily_usages.rb index 2db9f9148bab..6f245dc82d3a 100644 --- a/spec/factories/daily_usages.rb +++ b/spec/factories/daily_usages.rb @@ -9,6 +9,7 @@ external_subscription_id { subscription.external_id } from_datetime { Time.current.beginning_of_month } to_datetime { Time.current.end_of_month } + refreshed_at { Time.current } usage { {} } end end diff --git a/spec/factories/subscriptions.rb b/spec/factories/subscriptions.rb index b672dd684cd2..cae7daccb947 100644 --- a/spec/factories/subscriptions.rb +++ b/spec/factories/subscriptions.rb @@ -17,5 +17,9 @@ started_at { 1.month.ago } terminated_at { Time.zone.now } end + + trait :calendar do + billing_time { :calendar } + end end end diff --git a/spec/services/daily_usages/compute_all_service_spec.rb b/spec/services/daily_usages/compute_all_service_spec.rb index 993364eea8ac..c3c3f7fe92ea 100644 --- a/spec/services/daily_usages/compute_all_service_spec.rb +++ b/spec/services/daily_usages/compute_all_service_spec.rb @@ -33,7 +33,7 @@ end context 'when subscription usage was already computed' do - before { create(:daily_usage, subscription:, created_at: timestamp + 2.minutes) } + before { create(:daily_usage, subscription:, refreshed_at: timestamp + 2.minutes) } it 'does not enqueue any job' do expect(compute_service.call).to be_success diff --git a/spec/services/daily_usages/compute_service_spec.rb b/spec/services/daily_usages/compute_service_spec.rb index 0f138cbec6d0..4a1670b2bc07 100644 --- a/spec/services/daily_usages/compute_service_spec.rb +++ b/spec/services/daily_usages/compute_service_spec.rb @@ -7,7 +7,8 @@ let(:organization) { create(:organization) } let(:customer) { create(:customer, organization:) } - let(:subscription) { create(:subscription, customer:) } + let(:plan) { create(:plan, organization:) } + let(:subscription) { create(:subscription, :calendar, customer:, plan:, started_at: 1.year.ago) } let(:timestamp) { Time.zone.parse('2024-10-22 00:05:00') } @@ -20,14 +21,17 @@ organization_id: organization.id, customer_id: customer.id, subscription_id: subscription.id, - external_subscription_id: subscription.external_id - # TODO + external_subscription_id: subscription.external_id, + usage: Hash ) + expect(daily_usage.refreshed_at).to match_datetime(timestamp) + expect(daily_usage.from_datetime).to match_datetime(timestamp.beginning_of_month) + expect(daily_usage.to_datetime).to match_datetime(timestamp.end_of_month) end context 'when a daily usage already exists' do let(:existing_daily_usage) do - create(:daily_usage, subscription:, organization:, customer:, created_at: timestamp) + create(:daily_usage, subscription:, organization:, customer:, refreshed_at: timestamp) end before { existing_daily_usage } @@ -38,6 +42,36 @@ expect(result).to be_success expect(result.daily_usage).to eq(existing_daily_usage) end + + context 'when the organization has a timezone' do + let(:organization) { create(:organization, timezone: 'America/Sao_Paulo') } + + let(:existing_daily_usage) do + create(:daily_usage, subscription:, organization:, customer:, refreshed_at: timestamp - 4.hours) + end + + it 'takes the timezone into account' do + result = compute_service.call + + expect(result).to be_success + expect(result.daily_usage).to eq(existing_daily_usage) + end + end + + context 'when the customer has a timezone' do + 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) + end + + it 'takes the timezone into account' do + result = compute_service.call + + expect(result).to be_success + expect(result.daily_usage).to eq(existing_daily_usage) + end + end end end end