diff --git a/ee/app/models/license.rb b/ee/app/models/license.rb index ebb3af11940086648984857138843fbbe644f7ae..bcba572ab94bc348a95d35012e3e13ee64c32e1c 100644 --- a/ee/app/models/license.rb +++ b/ee/app/models/license.rb @@ -47,6 +47,7 @@ class License < ApplicationRecord after_create :update_trial_setting after_commit :reset_current after_commit :reset_future_dated, on: [:create, :destroy] + after_commit :update_billable_user_counts, on: :create scope :cloud, -> { where(cloud: true) } scope :recent, -> { reorder(id: :desc) } @@ -361,6 +362,11 @@ def update_trial_setting settings.update license_trial_ends_on: license.expires_at end + def update_billable_user_counts + identifier = Analytics::UsageTrends::Measurement.identifiers[:billable_users] + ::Analytics::UsageTrends::CounterJobWorker.perform_async(identifier, User.minimum(:id), User.maximum(:id), Time.zone.now) + end + def paid? [License::STARTER_PLAN, License::PREMIUM_PLAN, License::ULTIMATE_PLAN].include?(plan) end diff --git a/ee/spec/models/license_spec.rb b/ee/spec/models/license_spec.rb index f395a55b5a48a144c9ce066493c411cea9e2cb9c..ac92cee41eb082c7c36c4ada93fcdd25018e6412 100644 --- a/ee/spec/models/license_spec.rb +++ b/ee/spec/models/license_spec.rb @@ -18,6 +18,10 @@ def build_license_with_add_ons(add_ons, plan: nil) build(:license, data: gl_license.export) end + before do + allow(::Analytics::UsageTrends::CounterJobWorker).to receive(:perform_async) + end + describe 'validations' do describe '#valid_license' do subject(:license) { build(:license, data: gl_license.class.encryptor.encrypt(gl_license.to_json)) } @@ -626,6 +630,14 @@ def current_license_cached_value end end end + + describe '#update_billable_user_counts' do + subject!(:license) { create(:license, data: gl_license.export, starts_at: Date.current) } + + it 'updates billable user counts' do + expect(::Analytics::UsageTrends::CounterJobWorker).to have_received(:perform_async).once + end + end end describe 'Scopes' do diff --git a/ee/spec/requests/api/license_spec.rb b/ee/spec/requests/api/license_spec.rb index f8c12a0004c8c9e761503aabe50586f775e78f4c..3dcec170b170c57cf9c801af589382ccc669afdd 100644 --- a/ee/spec/requests/api/license_spec.rb +++ b/ee/spec/requests/api/license_spec.rb @@ -235,7 +235,7 @@ def license_json(license) end describe 'PUT /license/:id/refresh_billable_users' do - let(:license) { create(:license) } + let!(:license) { create(:license) } let(:endpoint) { "/license/#{license.id}/refresh_billable_users" } before do diff --git a/qa/qa/ee/resource/license.rb b/qa/qa/ee/resource/license.rb index 818be1fc6c9f9b1c01e0feb0a1bbbc23eb59ef7a..6bee5da2a5b0cd1bd3328d2a9d130b80e9587647 100644 --- a/qa/qa/ee/resource/license.rb +++ b/qa/qa/ee/resource/license.rb @@ -28,6 +28,10 @@ def delete_all(api_client = nil) instance(api_client).delete_all end + def current(api_client = nil) + instance(api_client).current + end + private def instance(api_client) @@ -132,6 +136,19 @@ def delete_all raise(ResourceNotDeletedError, "One or more licenses failed to delete: #{errors}") unless errors.empty? end + def current + current_license = parse_body(get(::QA::Runtime::API::Request.new(api_client, '/license').url)) + + License.init do |resource| + resource.id = current_license[:id] + resource.api_client = api_client + end + end + + def refresh_billable_users! + api_put_to("#{api_get_path}/refresh_billable_users", nil) + end + private # License key length diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb index da6ae0a9fefbb5ab18463158c8a08f2d3c958a62..8f34da1f902883744dd7ea057804673147a77458 100644 --- a/qa/qa/resource/api_fabricator.rb +++ b/qa/qa/resource/api_fabricator.rb @@ -150,7 +150,7 @@ def api_put def api_put_to(put_path, body) response = put(Runtime::API::Request.new(api_client, put_path).url, body) - unless response.code == HTTP_STATUS_OK + unless [HTTP_STATUS_OK, HTTP_STATUS_ACCEPTED].include? response.code raise(ResourceFabricationFailedError, <<~MSG.strip) Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`. #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])} diff --git a/qa/qa/specs/features/ee/browser_ui/11_fulfillment/utilization/user_registration_billing_spec.rb b/qa/qa/specs/features/ee/browser_ui/11_fulfillment/utilization/user_registration_billing_spec.rb index 3a1572ff81378c6f2c8ee6a2907eae83f5cd129f..c58a35d6c67f01fe340af10b412b238346d1ad08 100644 --- a/qa/qa/specs/features/ee/browser_ui/11_fulfillment/utilization/user_registration_billing_spec.rb +++ b/qa/qa/specs/features/ee/browser_ui/11_fulfillment/utilization/user_registration_billing_spec.rb @@ -15,6 +15,11 @@ module QA username: "qa-test-#{SecureRandom.hex(3)}") end + def refresh_billable_users_in_license + EE::Resource::License.current.refresh_billable_users! + sleep 5 # wait for billable users to be refreshed + end + before do # Enable sign-ups Runtime::ApplicationSettings.set_application_settings(signup_enabled: true) @@ -28,6 +33,7 @@ module QA end Flow::UserOnboarding.onboard_user + refresh_billable_users_in_license end after do @@ -60,6 +66,7 @@ module QA user.reload! && user.approve! # first reload the API resource to fetch the ID, then approve EE::Page::Admin::Dashboard.perform do |dashboard| + refresh_billable_users_in_license dashboard.refresh # Validate billable users has not changed after approval @@ -67,6 +74,7 @@ module QA group.add_member(user) # add the user to the group + refresh_billable_users_in_license dashboard.refresh # Validate billable users incremented by 1 @@ -74,6 +82,7 @@ module QA group.remove_member(user) # remove the user from the group + refresh_billable_users_in_license dashboard.refresh # Validate billable users equals the original amount